From: Darrick J. Wong <djwong@xxxxxxxxxx> Create a hook so that health monitoring can report filesystem shutdown events to userspace. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/xfs_fsops.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_fsops.h | 14 +++++++++++++ fs/xfs/xfs_mount.h | 3 +++ fs/xfs/xfs_super.c | 1 + 4 files changed, 75 insertions(+) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index a2929a0e0367e..ac2960c44bb84 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -483,6 +483,61 @@ xfs_fs_goingdown( return 0; } +#ifdef CONFIG_XFS_LIVE_HOOKS +DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_shutdown_hooks_switch); + +void +xfs_shutdown_hook_disable(void) +{ + xfs_hooks_switch_off(&xfs_shutdown_hooks_switch); +} + +void +xfs_shutdown_hook_enable(void) +{ + xfs_hooks_switch_on(&xfs_shutdown_hooks_switch); +} + +/* Call downstream hooks for a filesystem shutdown. */ +static inline void +xfs_shutdown_hook( + struct xfs_mount *mp, + uint32_t flags) +{ + if (xfs_hooks_switched_on(&xfs_shutdown_hooks_switch)) + xfs_hooks_call(&mp->m_shutdown_hooks, flags, NULL); +} + +/* Call the specified function during a shutdown update. */ +int +xfs_shutdown_hook_add( + struct xfs_mount *mp, + struct xfs_shutdown_hook *hook) +{ + return xfs_hooks_add(&mp->m_shutdown_hooks, &hook->shutdown_hook); +} + +/* Stop calling the specified function during a shutdown update. */ +void +xfs_shutdown_hook_del( + struct xfs_mount *mp, + struct xfs_shutdown_hook *hook) +{ + xfs_hooks_del(&mp->m_shutdown_hooks, &hook->shutdown_hook); +} + +/* Configure shutdown update hook functions. */ +void +xfs_shutdown_hook_setup( + struct xfs_shutdown_hook *hook, + notifier_fn_t mod_fn) +{ + xfs_hook_setup(&hook->shutdown_hook, mod_fn); +} +#else +# define xfs_shutdown_hook(...) ((void)0) +#endif /* CONFIG_XFS_LIVE_HOOKS */ + /* * Force a shutdown of the filesystem instantly while keeping the filesystem * consistent. We don't do an unmount here; just shutdown the shop, make sure @@ -541,6 +596,8 @@ xfs_do_force_shutdown( "Please unmount the filesystem and rectify the problem(s)"); if (xfs_error_level >= XFS_ERRLEVEL_HIGH) xfs_stack_trace(); + + xfs_shutdown_hook(mp, flags); } /* diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h index 3e2f73bcf8314..59df17decfbbf 100644 --- a/fs/xfs/xfs_fsops.h +++ b/fs/xfs/xfs_fsops.h @@ -14,4 +14,18 @@ int xfs_fs_goingdown(struct xfs_mount *mp, uint32_t inflags); int xfs_fs_reserve_ag_blocks(struct xfs_mount *mp); void xfs_fs_unreserve_ag_blocks(struct xfs_mount *mp); +#ifdef CONFIG_XFS_LIVE_HOOKS +struct xfs_shutdown_hook { + struct xfs_hook shutdown_hook; +}; + +void xfs_shutdown_hook_disable(void); +void xfs_shutdown_hook_enable(void); + +int xfs_shutdown_hook_add(struct xfs_mount *mp, struct xfs_shutdown_hook *hook); +void xfs_shutdown_hook_del(struct xfs_mount *mp, struct xfs_shutdown_hook *hook); +void xfs_shutdown_hook_setup(struct xfs_shutdown_hook *hook, + notifier_fn_t mod_fn); +#endif /* CONFIG_XFS_LIVE_HOOKS */ + #endif /* __XFS_FSOPS_H__ */ diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 316240b79a1e9..f1db647b94871 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -287,6 +287,9 @@ typedef struct xfs_mount { /* Hook to feed health events to a daemon. */ struct xfs_hooks m_health_update_hooks; + /* Hook to feed shutdown events to a daemon. */ + struct xfs_hooks m_shutdown_hooks; + struct xfs_timestats m_timestats; } xfs_mount_t; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 23dbb67a1344d..1ed848a3706be 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -2081,6 +2081,7 @@ static int xfs_init_fs_context( mp->m_allocsize_log = 16; /* 64k */ xfs_hooks_init(&mp->m_dir_update_hooks); + xfs_hooks_init(&mp->m_shutdown_hooks); xfs_hooks_init(&mp->m_health_update_hooks); xfs_timestats_init(mp);