[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210414134737.2366971-7-yi.zhang@huawei.com>
Date: Wed, 14 Apr 2021 21:47:36 +0800
From: Zhang Yi <yi.zhang@...wei.com>
To: <linux-ext4@...r.kernel.org>
CC: <linux-fsdevel@...r.kernel.org>, <tytso@....edu>,
<adilger.kernel@...ger.ca>, <jack@...e.cz>, <yi.zhang@...wei.com>,
<yukuai3@...wei.com>
Subject: [RFC PATCH v2 6/7] fs: introduce a usage count into the superblock
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@...wei.com>
---
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
Powered by blists - more mailing lists