From: Darrick J. Wong <[email protected]>

Create a hook so that health monitoring can report filesystem shutdown
events to userspace.

Signed-off-by: Darrick J. Wong <[email protected]>
---
 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);
 


Reply via email to