Commit <87d8fe1ee6b8> ("add releasepage hooks to block devices which can be used by file systems") introduce a hook that used by ext4 filesystem to release journal buffers, but it doesn't add corresponding concurrency protection that ->bdev_try_to_free_page() could be raced by umount filesystem concurrently. This patch add a usage count on superblock that filesystem can use it to prevent above race and make invoke ->bdev_try_to_free_page() safe. Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx> --- include/linux/fs.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index ec8f3ddf4a6a..3c6a5c08c2df 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -41,6 +41,7 @@ #include <linux/stddef.h> #include <linux/mount.h> #include <linux/cred.h> +#include <linux/percpu-refcount.h> #include <asm/byteorder.h> #include <uapi/linux/fs.h> @@ -1547,6 +1548,13 @@ struct super_block { spinlock_t s_inode_wblist_lock; struct list_head s_inodes_wb; /* writeback inodes */ + + /* + * Count users who are using the super_block, used to protect + * umount filesystem concurrently with others. + */ + struct percpu_ref s_usage_counter; + wait_queue_head_t s_usage_waitq; } __randomize_layout; /* Helper functions so that in most cases filesystems will @@ -1765,6 +1773,27 @@ static inline bool sb_start_intwrite_trylock(struct super_block *sb) bool inode_owner_or_capable(struct user_namespace *mnt_userns, const struct inode *inode); +static inline void sb_usage_counter_release(struct percpu_ref *ref) +{ + struct super_block *sb; + + sb = container_of(ref, struct super_block, s_usage_counter); + wake_up(&sb->s_usage_waitq); +} + +static inline int sb_usage_counter_init(struct super_block *sb) +{ + init_waitqueue_head(&sb->s_usage_waitq); + return percpu_ref_init(&sb->s_usage_counter, sb_usage_counter_release, + 0, GFP_KERNEL); +} + +static inline void sb_usage_counter_wait(struct super_block *sb) +{ + percpu_ref_kill(&sb->s_usage_counter); + wait_event(sb->s_usage_waitq, percpu_ref_is_zero(&sb->s_usage_counter)); +} + /* * VFS helper functions.. */ -- 2.25.4