From: Chi Zhiling <chizhiling@163.com>
To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org
Cc: Namjae Jeon <linkinjeon@kernel.org>,
Sungjong Seo <sj1557.seo@samsung.com>,
Yuezhang Mo <yuezhang.mo@sony.com>,
Chi Zhiling <chizhiling@kylinos.cn>
Subject: [RFC PATCH v1 5/6] exfat: convert s_lock mutex to rw_semaphore using write lock
Date: Fri, 21 Aug 2026 18:05:30 +0800 [thread overview]
Message-ID: <20260821100531.998196-6-chizhiling@163.com> (raw)
In-Reply-To: <20260821100531.998196-1-chizhiling@163.com>
From: Chi Zhiling <chizhiling@kylinos.cn>
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 <chizhiling@kylinos.cn>
---
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
next prev parent reply other threads:[~2026-08-21 10:06 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 10:05 [RFC PATCH 0/6] exfat: take s_lock in read mode for iomap mapping paths Chi Zhiling
2026-08-21 10:05 ` [RFC PATCH v1 1/6] exfat: remove dead hint_bmap updates in I/O and truncate paths Chi Zhiling
2026-08-21 10:05 ` [RFC PATCH v1 2/6] exfat: take bitmap_lock at the start of exfat_alloc_cluster() Chi Zhiling
2026-08-21 10:05 ` [RFC PATCH v1 3/6] exfat: use atomic bit ops for volume dirty flag Chi Zhiling
2026-08-21 10:05 ` [RFC PATCH v1 4/6] exfat: lock FAT2 buffer while copying mirrored FAT entries Chi Zhiling
2026-08-21 10:05 ` Chi Zhiling [this message]
2026-08-21 10:05 ` [RFC PATCH v1 6/6] exfat: take s_lock in read mode for iomap mapping paths Chi Zhiling
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260821100531.998196-6-chizhiling@163.com \
--to=chizhiling@163.com \
--cc=chizhiling@kylinos.cn \
--cc=exfat@lists.linux.dev \
--cc=linkinjeon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sj1557.seo@samsung.com \
--cc=yuezhang.mo@sony.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.