[RFC PATCH v2 6/7] fs: introduce a usage count into the superblock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux