Skip to content

Commit 25ca57f

Browse files
author
Darrick J. Wong
committed
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: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent b3a289a commit 25ca57f

4 files changed

Lines changed: 43 additions & 2 deletions

File tree

fs/xfs/libxfs/xfs_fs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,9 @@ struct xfs_rtgroup_geometry {
10141014
#define XFS_HEALTH_MONITOR_TYPE_RUNNING (0)
10151015
#define XFS_HEALTH_MONITOR_TYPE_LOST (1)
10161016

1017+
/* filesystem was unmounted */
1018+
#define XFS_HEALTH_MONITOR_TYPE_UNMOUNT (2)
1019+
10171020
/* lost events */
10181021
struct xfs_health_monitor_lost {
10191022
__u64 count;

fs/xfs/xfs_healthmon.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ xfs_healthmon_put(
9090
kfree(event);
9191
}
9292

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

167168
switch (existing->type) {
168169
case XFS_HEALTHMON_RUNNING:
170+
case XFS_HEALTHMON_UNMOUNT:
169171
/* should only ever be one of these events anyway */
170172
return false;
171173

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

310-
/* Detach the xfs mount from this healthmon instance. */
312+
/*
313+
* Report that the filesystem is being unmounted, then detach the xfs mount
314+
* from this healthmon instance.
315+
*/
311316
void
312317
xfs_healthmon_unmount(
313318
struct xfs_mount *mp)
@@ -317,6 +322,17 @@ xfs_healthmon_unmount(
317322
if (!hm)
318323
return;
319324

325+
trace_xfs_healthmon_report_unmount(hm);
326+
327+
/*
328+
* Insert the unmount notification at the start of the event queue so
329+
* that userspace knows the filesystem went away as soon as possible.
330+
* There's nothing actionable for userspace after an unmount. Once
331+
* we've inserted the unmount event, hm no longer owns that event.
332+
*/
333+
__xfs_healthmon_insert(hm, hm->unmount_event);
334+
hm->unmount_event = NULL;
335+
320336
xfs_healthmon_detach(hm);
321337
xfs_healthmon_put(hm);
322338
}
@@ -713,6 +729,20 @@ xfs_ioc_health_monitor(
713729
running_event->domain = XFS_HEALTHMON_MOUNT;
714730
__xfs_healthmon_insert(hm, running_event);
715731

732+
/*
733+
* Preallocate the unmount event so that we can't fail to notify the
734+
* filesystem later. This is key for triggering fast exit of the
735+
* xfs_healer daemon.
736+
*/
737+
hm->unmount_event = kzalloc(sizeof(struct xfs_healthmon_event),
738+
GFP_NOFS);
739+
if (!hm->unmount_event) {
740+
ret = -ENOMEM;
741+
goto out_hm;
742+
}
743+
hm->unmount_event->type = XFS_HEALTHMON_UNMOUNT;
744+
hm->unmount_event->domain = XFS_HEALTHMON_MOUNT;
745+
716746
/*
717747
* Try to attach this health monitor to the xfs_mount. The monitor is
718748
* considered live and will receive events if this succeeds.

fs/xfs/xfs_healthmon.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ struct xfs_healthmon {
3434
struct xfs_healthmon_event *first_event;
3535
struct xfs_healthmon_event *last_event;
3636

37+
/* preallocated event for unmount */
38+
struct xfs_healthmon_event *unmount_event;
39+
3740
/* number of events in the list */
3841
unsigned int events;
3942

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

7276
enum xfs_healthmon_domain {

fs/xfs/xfs_trace.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6005,14 +6005,18 @@ DEFINE_HEALTHMON_EVENT(xfs_healthmon_read_start);
60056005
DEFINE_HEALTHMON_EVENT(xfs_healthmon_read_finish);
60066006
DEFINE_HEALTHMON_EVENT(xfs_healthmon_release);
60076007
DEFINE_HEALTHMON_EVENT(xfs_healthmon_detach);
6008+
DEFINE_HEALTHMON_EVENT(xfs_healthmon_report_unmount);
60086009

60096010
#define XFS_HEALTHMON_TYPE_STRINGS \
6010-
{ XFS_HEALTHMON_LOST, "lost" }
6011+
{ XFS_HEALTHMON_LOST, "lost" }, \
6012+
{ XFS_HEALTHMON_UNMOUNT, "unmount" }
60116013

60126014
#define XFS_HEALTHMON_DOMAIN_STRINGS \
60136015
{ XFS_HEALTHMON_MOUNT, "mount" }
60146016

60156017
TRACE_DEFINE_ENUM(XFS_HEALTHMON_LOST);
6018+
TRACE_DEFINE_ENUM(XFS_HEALTHMON_UNMOUNT);
6019+
60166020
TRACE_DEFINE_ENUM(XFS_HEALTHMON_MOUNT);
60176021

60186022
DECLARE_EVENT_CLASS(xfs_healthmon_event_class,

0 commit comments

Comments
 (0)