xref: /linux/fs/xfs/xfs_hooks.h (revision 4e98cc905c0fec337416e9fd7ca4f75607a6de99)
1*4e98cc90SDarrick J. Wong // SPDX-License-Identifier: GPL-2.0-or-later
2*4e98cc90SDarrick J. Wong /*
3*4e98cc90SDarrick J. Wong  * Copyright (c) 2022-2024 Oracle.  All Rights Reserved.
4*4e98cc90SDarrick J. Wong  * Author: Darrick J. Wong <djwong@kernel.org>
5*4e98cc90SDarrick J. Wong  */
6*4e98cc90SDarrick J. Wong #ifndef XFS_HOOKS_H_
7*4e98cc90SDarrick J. Wong #define XFS_HOOKS_H_
8*4e98cc90SDarrick J. Wong 
9*4e98cc90SDarrick J. Wong #ifdef CONFIG_XFS_LIVE_HOOKS
10*4e98cc90SDarrick J. Wong struct xfs_hooks {
11*4e98cc90SDarrick J. Wong 	struct blocking_notifier_head	head;
12*4e98cc90SDarrick J. Wong };
13*4e98cc90SDarrick J. Wong 
14*4e98cc90SDarrick J. Wong /*
15*4e98cc90SDarrick J. Wong  * If jump labels are enabled in Kconfig, the static key uses nop sleds and
16*4e98cc90SDarrick J. Wong  * code patching to eliminate the overhead of taking the rwsem in
17*4e98cc90SDarrick J. Wong  * blocking_notifier_call_chain when there are no hooks configured.  If not,
18*4e98cc90SDarrick J. Wong  * the static key per-call overhead is an atomic read.  Most arches that can
19*4e98cc90SDarrick J. Wong  * handle XFS also support jump labels.
20*4e98cc90SDarrick J. Wong  *
21*4e98cc90SDarrick J. Wong  * Note: Patching the kernel code requires taking the cpu hotplug lock.  Other
22*4e98cc90SDarrick J. Wong  * parts of the kernel allocate memory with that lock held, which means that
23*4e98cc90SDarrick J. Wong  * XFS callers cannot hold any locks that might be used by memory reclaim or
24*4e98cc90SDarrick J. Wong  * writeback when calling the static_branch_{inc,dec} functions.
25*4e98cc90SDarrick J. Wong  */
26*4e98cc90SDarrick J. Wong # define DEFINE_STATIC_XFS_HOOK_SWITCH(name) \
27*4e98cc90SDarrick J. Wong 	static DEFINE_STATIC_KEY_FALSE(name)
28*4e98cc90SDarrick J. Wong # define xfs_hooks_switch_on(name)	static_branch_inc(name)
29*4e98cc90SDarrick J. Wong # define xfs_hooks_switch_off(name)	static_branch_dec(name)
30*4e98cc90SDarrick J. Wong # define xfs_hooks_switched_on(name)	static_branch_unlikely(name)
31*4e98cc90SDarrick J. Wong 
32*4e98cc90SDarrick J. Wong struct xfs_hook {
33*4e98cc90SDarrick J. Wong 	/* This must come at the start of the structure. */
34*4e98cc90SDarrick J. Wong 	struct notifier_block		nb;
35*4e98cc90SDarrick J. Wong };
36*4e98cc90SDarrick J. Wong 
37*4e98cc90SDarrick J. Wong typedef	int (*xfs_hook_fn_t)(struct xfs_hook *hook, unsigned long action,
38*4e98cc90SDarrick J. Wong 		void *data);
39*4e98cc90SDarrick J. Wong 
40*4e98cc90SDarrick J. Wong void xfs_hooks_init(struct xfs_hooks *chain);
41*4e98cc90SDarrick J. Wong int xfs_hooks_add(struct xfs_hooks *chain, struct xfs_hook *hook);
42*4e98cc90SDarrick J. Wong void xfs_hooks_del(struct xfs_hooks *chain, struct xfs_hook *hook);
43*4e98cc90SDarrick J. Wong int xfs_hooks_call(struct xfs_hooks *chain, unsigned long action,
44*4e98cc90SDarrick J. Wong 		void *priv);
45*4e98cc90SDarrick J. Wong 
46*4e98cc90SDarrick J. Wong static inline void xfs_hook_setup(struct xfs_hook *hook, notifier_fn_t fn)
47*4e98cc90SDarrick J. Wong {
48*4e98cc90SDarrick J. Wong 	hook->nb.notifier_call = fn;
49*4e98cc90SDarrick J. Wong 	hook->nb.priority = 0;
50*4e98cc90SDarrick J. Wong }
51*4e98cc90SDarrick J. Wong 
52*4e98cc90SDarrick J. Wong #else
53*4e98cc90SDarrick J. Wong 
54*4e98cc90SDarrick J. Wong struct xfs_hooks { /* empty */ };
55*4e98cc90SDarrick J. Wong 
56*4e98cc90SDarrick J. Wong # define DEFINE_STATIC_XFS_HOOK_SWITCH(name)
57*4e98cc90SDarrick J. Wong # define xfs_hooks_switch_on(name)		((void)0)
58*4e98cc90SDarrick J. Wong # define xfs_hooks_switch_off(name)		((void)0)
59*4e98cc90SDarrick J. Wong # define xfs_hooks_switched_on(name)		(false)
60*4e98cc90SDarrick J. Wong 
61*4e98cc90SDarrick J. Wong # define xfs_hooks_init(chain)			((void)0)
62*4e98cc90SDarrick J. Wong # define xfs_hooks_call(chain, val, priv)	(NOTIFY_DONE)
63*4e98cc90SDarrick J. Wong #endif
64*4e98cc90SDarrick J. Wong 
65*4e98cc90SDarrick J. Wong #endif /* XFS_HOOKS_H_ */
66