@@ -480,6 +480,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
@@ -538,6 +593,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);
}
/*
@@ -15,4 +15,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__ */
@@ -343,6 +343,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;
} xfs_mount_t;
#define M_IGEO(mp) (&(mp)->m_ino_geo)
@@ -2182,6 +2182,7 @@ 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);
fc->s_fs_info = mp;