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