From: Chuck Lever Modular filesystems currently have no notification mechanism for mount teardown. When an NFS export is unexported then unmounted, NFSD cannot detect this event to revoke associated state, state which holds open file references that pin the mount. The existing fs_pin infrastructure provides unmount callbacks, but pin_insert() and pin_remove() lack EXPORT_SYMBOL_GPL(), restricting this facility to built-in subsystems. This restriction appears historical rather than intentional; fs_pin.h is already a public header, and the mechanism's purpose (coordinating mount lifetimes with filesystem state) applies equally to modular subsystems. Export both symbols with EXPORT_SYMBOL_GPL() to permit modular filesystems to register fs_pin callbacks. NFSD requires this to revoke NFSv4 delegations, layouts, and open state when the underlying filesystem is unmounted, preventing use-after-free conditions in the state tracking layer. Reviewed-by: NeilBrown Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- fs/fs_pin.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/fs/fs_pin.c b/fs/fs_pin.c index 47ef3c71ce90..972f34558b97 100644 --- a/fs/fs_pin.c +++ b/fs/fs_pin.c @@ -1,4 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 +#include #include #include #include @@ -7,6 +8,15 @@ static DEFINE_SPINLOCK(pin_lock); +/** + * pin_remove - detach an fs_pin from its mount and superblock + * @pin: the pin to remove + * + * Removes @pin from the mount and superblock pin lists and marks it + * done. Must be called from the pin's kill callback before returning. + * The caller must keep @pin valid until this function returns; after + * that, VFS will not reference @pin again. + */ void pin_remove(struct fs_pin *pin) { spin_lock(&pin_lock); @@ -18,7 +28,17 @@ void pin_remove(struct fs_pin *pin) wake_up_locked(&pin->wait); spin_unlock_irq(&pin->wait.lock); } +EXPORT_SYMBOL_GPL(pin_remove); +/** + * pin_insert - register an fs_pin for unmount notification + * @pin: the pin to register (must be initialized with init_fs_pin()) + * @m: the vfsmount to monitor + * + * Registers @pin to receive notification when @m is unmounted. When + * unmount occurs, the pin's kill callback is invoked with the RCU + * read lock held. The callback must call pin_remove() before returning. + */ void pin_insert(struct fs_pin *pin, struct vfsmount *m) { spin_lock(&pin_lock); @@ -26,6 +46,7 @@ void pin_insert(struct fs_pin *pin, struct vfsmount *m) hlist_add_head(&pin->m_list, &real_mount(m)->mnt_pins); spin_unlock(&pin_lock); } +EXPORT_SYMBOL_GPL(pin_insert); void pin_kill(struct fs_pin *p) { -- 2.52.0