Commit 25ca57fa authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: convey filesystem unmount events to the health monitor



In xfs_healthmon_unmount, send events to xfs_healer so that it knows
that nothing further can be done for the filesystem.

Signed-off-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent b3a289a2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1014,6 +1014,9 @@ struct xfs_rtgroup_geometry {
#define XFS_HEALTH_MONITOR_TYPE_RUNNING		(0)
#define XFS_HEALTH_MONITOR_TYPE_LOST		(1)

/* filesystem was unmounted */
#define XFS_HEALTH_MONITOR_TYPE_UNMOUNT		(2)

/* lost events */
struct xfs_health_monitor_lost {
	__u64	count;
+31 −1
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ xfs_healthmon_put(
			kfree(event);
		}

		kfree(hm->unmount_event);
		kfree(hm->buffer);
		mutex_destroy(&hm->lock);
		kfree_rcu_mightsleep(hm);
@@ -166,6 +167,7 @@ xfs_healthmon_merge_events(

	switch (existing->type) {
	case XFS_HEALTHMON_RUNNING:
	case XFS_HEALTHMON_UNMOUNT:
		/* should only ever be one of these events anyway */
		return false;

@@ -307,7 +309,10 @@ xfs_healthmon_push(
	return error;
}

/* Detach the xfs mount from this healthmon instance. */
/*
 * Report that the filesystem is being unmounted, then detach the xfs mount
 * from this healthmon instance.
 */
void
xfs_healthmon_unmount(
	struct xfs_mount		*mp)
@@ -317,6 +322,17 @@ xfs_healthmon_unmount(
	if (!hm)
		return;

	trace_xfs_healthmon_report_unmount(hm);

	/*
	 * Insert the unmount notification at the start of the event queue so
	 * that userspace knows the filesystem went away as soon as possible.
	 * There's nothing actionable for userspace after an unmount.  Once
	 * we've inserted the unmount event, hm no longer owns that event.
	 */
	__xfs_healthmon_insert(hm, hm->unmount_event);
	hm->unmount_event = NULL;

	xfs_healthmon_detach(hm);
	xfs_healthmon_put(hm);
}
@@ -713,6 +729,20 @@ xfs_ioc_health_monitor(
	running_event->domain = XFS_HEALTHMON_MOUNT;
	__xfs_healthmon_insert(hm, running_event);

	/*
	 * Preallocate the unmount event so that we can't fail to notify the
	 * filesystem later.  This is key for triggering fast exit of the
	 * xfs_healer daemon.
	 */
	hm->unmount_event = kzalloc(sizeof(struct xfs_healthmon_event),
			GFP_NOFS);
	if (!hm->unmount_event) {
		ret = -ENOMEM;
		goto out_hm;
	}
	hm->unmount_event->type = XFS_HEALTHMON_UNMOUNT;
	hm->unmount_event->domain = XFS_HEALTHMON_MOUNT;

	/*
	 * Try to attach this health monitor to the xfs_mount.  The monitor is
	 * considered live and will receive events if this succeeds.
+4 −0
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@ struct xfs_healthmon {
	struct xfs_healthmon_event	*first_event;
	struct xfs_healthmon_event	*last_event;

	/* preallocated event for unmount */
	struct xfs_healthmon_event	*unmount_event;

	/* number of events in the list */
	unsigned int			events;

@@ -67,6 +70,7 @@ void xfs_healthmon_unmount(struct xfs_mount *mp);
enum xfs_healthmon_type {
	XFS_HEALTHMON_RUNNING,	/* monitor running */
	XFS_HEALTHMON_LOST,	/* message lost */
	XFS_HEALTHMON_UNMOUNT,	/* filesystem is unmounting */
};

enum xfs_healthmon_domain {
+5 −1
Original line number Diff line number Diff line
@@ -6005,14 +6005,18 @@ DEFINE_HEALTHMON_EVENT(xfs_healthmon_read_start);
DEFINE_HEALTHMON_EVENT(xfs_healthmon_read_finish);
DEFINE_HEALTHMON_EVENT(xfs_healthmon_release);
DEFINE_HEALTHMON_EVENT(xfs_healthmon_detach);
DEFINE_HEALTHMON_EVENT(xfs_healthmon_report_unmount);

#define XFS_HEALTHMON_TYPE_STRINGS \
	{ XFS_HEALTHMON_LOST,		"lost" }
	{ XFS_HEALTHMON_LOST,		"lost" }, \
	{ XFS_HEALTHMON_UNMOUNT,	"unmount" }

#define XFS_HEALTHMON_DOMAIN_STRINGS \
	{ XFS_HEALTHMON_MOUNT,		"mount" }

TRACE_DEFINE_ENUM(XFS_HEALTHMON_LOST);
TRACE_DEFINE_ENUM(XFS_HEALTHMON_UNMOUNT);

TRACE_DEFINE_ENUM(XFS_HEALTHMON_MOUNT);

DECLARE_EVENT_CLASS(xfs_healthmon_event_class,