[RFC PATCH v1 5/6] exfat: convert s_lock mutex to rw_semaphore using write lock

Chi Zhiling <[email protected]>
Newsgroups dev.linux.lists.exfat,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
From: Chi Zhiling <[email protected]>

Convert sbi->s_lock from a mutex to an rw_semaphore and acquire it in
write mode at every existing use site. This is a mechanical conversion
with no behavioral change, preparing the lock for read-mode access in
the iomap mapping paths so that concurrent mappings of distinct inodes
can proceed in parallel.

Lock ordering stays consistent (inode_lock -> s_lock -> bitmap_lock),
so no deadlock is introduced.

Signed-off-by: Chi Zhiling <[email protected]>
---
 fs/exfat/dir.c      | 14 +++++++-------
 fs/exfat/exfat_fs.h |  2 +-
 fs/exfat/file.c     |  4 ++--
 fs/exfat/inode.c    | 10 +++++-----
 fs/exfat/iomap.c    |  4 ++--
 fs/exfat/namei.c    | 26 +++++++++++++-------------
 fs/exfat/super.c    | 10 +++++-----
 7 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index fe73b1380c5d..ea454574260e 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -223,7 +223,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
 	if (err)
 		goto out;
 get_new:
-	mutex_lock(&EXFAT_SB(sb)->s_lock);
+	down_write(&EXFAT_SB(sb)->s_lock);
 
 	if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
 		goto end_of_dir;
@@ -255,7 +255,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
 		inum = iunique(sb, EXFAT_ROOT_INO);
 	}
 
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 	if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum,
 			(de.attr & EXFAT_ATTR_SUBDIR) ? DT_DIR : DT_REG))
 		goto out;
@@ -266,7 +266,7 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
 	if (!cpos && fake_offset)
 		cpos = ITER_POS_FILLED_DOTS;
 	ctx->pos = cpos;
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 out:
 	/*
 	 * To improve performance, free namebuf after unlock sb_lock.
@@ -1294,7 +1294,7 @@ int exfat_read_volume_label(struct super_block *sb, struct exfat_uni_name *label
 	struct exfat_entry_set_cache es;
 	struct exfat_dentry *ep;
 
-	mutex_lock(&sbi->s_lock);
+	down_write(&sbi->s_lock);
 
 	memset(label_out, 0, sizeof(*label_out));
 	ret = exfat_get_volume_label_dentry(sb, &es);
@@ -1322,7 +1322,7 @@ int exfat_read_volume_label(struct super_block *sb, struct exfat_uni_name *label
 
 	exfat_put_dentry_set(&es, false);
 unlock:
-	mutex_unlock(&sbi->s_lock);
+	up_write(&sbi->s_lock);
 	return ret;
 }
 
@@ -1339,7 +1339,7 @@ int exfat_write_volume_label(struct super_block *sb,
 	if (label->name_len > EXFAT_VOLUME_LABEL_LEN)
 		return -EINVAL;
 
-	mutex_lock(&sbi->s_lock);
+	down_write(&sbi->s_lock);
 
 	ret = exfat_get_volume_label_dentry(sb, &es);
 	if (ret == -ENOENT) {
@@ -1376,6 +1376,6 @@ int exfat_write_volume_label(struct super_block *sb,
 	ret = exfat_put_dentry_set(&es, IS_DIRSYNC(root_inode));
 
 unlock:
-	mutex_unlock(&sbi->s_lock);
+	up_write(&sbi->s_lock);
 	return ret;
 }
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index f1505c013248..16ce508e0946 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -246,7 +246,7 @@ struct exfat_sb_info {
 
 	unsigned long s_exfat_flags; /* Exfat superblock flags */
 
-	struct mutex s_lock; /* superblock lock */
+	struct rw_semaphore s_lock; /* superblock lock */
 	struct mutex bitmap_lock; /* bitmap lock */
 	struct exfat_mount_options options;
 	struct nls_table *nls_io; /* Charset used for input and display */
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index 29c5db12288e..8abef3d2294a 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -297,7 +297,7 @@ static void exfat_truncate(struct inode *inode)
 	struct exfat_inode_info *ei = EXFAT_I(inode);
 	int err;
 
-	mutex_lock(&sbi->s_lock);
+	down_write(&sbi->s_lock);
 	if (ei->start_clu == 0) {
 		/*
 		 * Empty start_clu != ~0 (not allocated)
@@ -312,7 +312,7 @@ static void exfat_truncate(struct inode *inode)
 
 	inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >> 9;
 write_size:
-	mutex_unlock(&sbi->s_lock);
+	up_write(&sbi->s_lock);
 }
 
 int exfat_getattr(struct mnt_idmap *idmap, const struct path *path,
diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
index d041f893b1c3..a89826e08e1c 100644
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@ -116,16 +116,16 @@ int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
 	if (unlikely(exfat_forced_shutdown(inode->i_sb)))
 		return -EIO;
 
-	mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
+	down_write(&EXFAT_SB(inode->i_sb)->s_lock);
 	ret = __exfat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
-	mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
+	up_write(&EXFAT_SB(inode->i_sb)->s_lock);
 
 	return ret;
 }
 
 void exfat_sync_inode(struct inode *inode)
 {
-	lockdep_assert_held(&EXFAT_SB(inode->i_sb)->s_lock);
+	lockdep_assert_held_write(&EXFAT_SB(inode->i_sb)->s_lock);
 	__exfat_write_inode(inode, 1);
 }
 
@@ -443,9 +443,9 @@ void exfat_evict_inode(struct inode *inode)
 
 	if (!inode->i_nlink) {
 		i_size_write(inode, 0);
-		mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
+		down_write(&EXFAT_SB(inode->i_sb)->s_lock);
 		__exfat_truncate(inode);
-		mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
+		up_write(&EXFAT_SB(inode->i_sb)->s_lock);
 	}
 
 	clear_inode(inode);
diff --git a/fs/exfat/iomap.c b/fs/exfat/iomap.c
index 0c805bf6676a..bc8bdfa9bb80 100644
--- a/fs/exfat/iomap.c
+++ b/fs/exfat/iomap.c
@@ -68,7 +68,7 @@ static int __exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length
 	num_clusters = exfat_bytes_to_cluster_round_up(sbi,
 			offset + length) - exfat_bytes_to_cluster(sbi, offset);
 
-	mutex_lock(&sbi->s_lock);
+	down_write(&sbi->s_lock);
 	iomap->bdev = inode->i_sb->s_bdev;
 	iomap->offset = offset;
 
@@ -135,7 +135,7 @@ static int __exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length
 
 	iomap->flags |= IOMAP_F_MERGED;
 out:
-	mutex_unlock(&sbi->s_lock);
+	up_write(&sbi->s_lock);
 	return err;
 }
 
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index f26f987a34cf..0c28040e97d6 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -565,7 +565,7 @@ static int exfat_create(struct mnt_idmap *idmap, struct inode *dir,
 	if (unlikely(exfat_forced_shutdown(sb)))
 		return -EIO;
 
-	mutex_lock(&EXFAT_SB(sb)->s_lock);
+	down_write(&EXFAT_SB(sb)->s_lock);
 	exfat_set_volume_dirty(sb);
 	err = exfat_add_entry(dir, dentry->d_name.name, TYPE_FILE, &info);
 	if (err)
@@ -592,7 +592,7 @@ static int exfat_create(struct mnt_idmap *idmap, struct inode *dir,
 
 	d_instantiate(dentry, inode);
 unlock:
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 	return err;
 }
 
@@ -732,7 +732,7 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
 	int err;
 	loff_t i_pos;
 
-	mutex_lock(&EXFAT_SB(sb)->s_lock);
+	down_write(&EXFAT_SB(sb)->s_lock);
 	err = exfat_find(dir, &dentry->d_name, &info);
 	if (err) {
 		if (unlikely(err != -ENOENT))
@@ -761,12 +761,12 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
 		 */
 		d_move(alias, dentry);
 		iput(inode);
-		mutex_unlock(&EXFAT_SB(sb)->s_lock);
+		up_write(&EXFAT_SB(sb)->s_lock);
 		return alias;
 	}
 	dput(alias);
 out:
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 	if (!inode)
 		exfat_d_version_set(dentry, inode_query_iversion(dir));
 
@@ -785,7 +785,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
 	if (unlikely(exfat_forced_shutdown(sb)))
 		return -EIO;
 
-	mutex_lock(&EXFAT_SB(sb)->s_lock);
+	down_write(&EXFAT_SB(sb)->s_lock);
 	if (ei->dir.dir == DIR_DELETED) {
 		exfat_err(sb, "abnormal access to deleted dentry");
 		err = -ENOENT;
@@ -821,7 +821,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
 	exfat_unhash_inode(inode);
 	exfat_d_version_set(dentry, inode_query_iversion(dir));
 unlock:
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 	return err;
 }
 
@@ -838,7 +838,7 @@ static struct dentry *exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
 	if (unlikely(exfat_forced_shutdown(sb)))
 		return ERR_PTR(-EIO);
 
-	mutex_lock(&EXFAT_SB(sb)->s_lock);
+	down_write(&EXFAT_SB(sb)->s_lock);
 	exfat_set_volume_dirty(sb);
 	err = exfat_add_entry(dir, dentry->d_name.name, TYPE_DIR, &info);
 	if (err)
@@ -867,7 +867,7 @@ static struct dentry *exfat_mkdir(struct mnt_idmap *idmap, struct inode *dir,
 	d_instantiate(dentry, inode);
 
 unlock:
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 	return err ? ERR_PTR(err) : NULL;
 }
 
@@ -929,7 +929,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 	if (unlikely(exfat_forced_shutdown(sb)))
 		return -EIO;
 
-	mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock);
+	down_write(&EXFAT_SB(inode->i_sb)->s_lock);
 
 	if (ei->dir.dir == DIR_DELETED) {
 		exfat_err(sb, "abnormal access to deleted dentry");
@@ -979,7 +979,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
 	exfat_unhash_inode(inode);
 	exfat_d_version_set(dentry, inode_query_iversion(dir));
 unlock:
-	mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock);
+	up_write(&EXFAT_SB(inode->i_sb)->s_lock);
 	return err;
 }
 
@@ -1282,7 +1282,7 @@ static int exfat_rename(struct mnt_idmap *idmap,
 	if (flags & ~RENAME_NOREPLACE)
 		return -EINVAL;
 
-	mutex_lock(&EXFAT_SB(sb)->s_lock);
+	down_write(&EXFAT_SB(sb)->s_lock);
 	old_inode = old_dentry->d_inode;
 	new_inode = new_dentry->d_inode;
 
@@ -1334,7 +1334,7 @@ static int exfat_rename(struct mnt_idmap *idmap,
 	}
 
 unlock:
-	mutex_unlock(&EXFAT_SB(sb)->s_lock);
+	up_write(&EXFAT_SB(sb)->s_lock);
 	return err;
 }
 
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index 491273d8eeb6..72a35f4079b4 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -45,11 +45,11 @@ static void exfat_put_super(struct super_block *sb)
 {
 	struct exfat_sb_info *sbi = EXFAT_SB(sb);
 
-	mutex_lock(&sbi->s_lock);
+	down_write(&sbi->s_lock);
 	exfat_clear_volume_dirty(sb);
 	exfat_free_bitmap(sbi);
 	brelse(sbi->boot_bh);
-	mutex_unlock(&sbi->s_lock);
+	up_write(&sbi->s_lock);
 }
 
 static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -771,9 +771,9 @@ static int exfat_reconfigure(struct fs_context *fc)
 	fc->sb_flags |= SB_NODIRATIME;
 
 	sync_filesystem(sb);
-	mutex_lock(&sbi->s_lock);
+	down_write(&sbi->s_lock);
 	exfat_clear_volume_dirty(sb);
-	mutex_unlock(&sbi->s_lock);
+	up_write(&sbi->s_lock);
 
 	if (new_opts->allow_utime == (unsigned short)-1)
 		new_opts->allow_utime = ~new_opts->fs_dmask & 0022;
@@ -820,7 +820,7 @@ static int exfat_init_fs_context(struct fs_context *fc)
 	if (!sbi)
 		return -ENOMEM;
 
-	mutex_init(&sbi->s_lock);
+	init_rwsem(&sbi->s_lock);
 	mutex_init(&sbi->bitmap_lock);
 	ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
 			DEFAULT_RATELIMIT_BURST);
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.