From nobody Mon Sep 28 13:17:34 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EDDE3BFAC8 for ; Fri, 21 Aug 2026 10:06:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306822; cv=none; b=O69j+BEvZSTowpdIBs/EOYQGoBXOAHhffxEEoCa+W98NfZLwSClaRmyYkoQnO+JFmT48CDfl5TsZgO0dTFU1kyr8zJTuYYi/TikP6OsasLcGxQURCgZH3jKNMtwiEh2VL4MRnSA/5mfBZ+sYQ6ds9DZFbA3W7H6o5Dktwko8kks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306822; c=relaxed/simple; bh=3pHytC5W1iaPKvgjIDJOsJhN+T7PeLFM3FhBfRKFzIw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bBGlYrFBsho+hxASyyKWmHlmCg3rlSgAC2xleQXYixyexNXPzh8ppkBWqorEvLh2G1S9Y9QSdTUVffHyYvLUW40Y/mSHIKud9Lbpq4ma3SYgHLKbRfA5ge0fr8lnN+gYQmV2XX5MAfhjxxM7D1pgVH/gNsFMtkK1ZuhTk1nxRL4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=S5mgI/3k; arc=none smtp.client-ip=220.197.31.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="S5mgI/3k" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=j2 ssn6cZSg9CgKxjgsMw4fWNsLvCQcbmWr4c+fVdioc=; b=S5mgI/3k8bKzFlZ7A6 bUDQMTPXELWfg4kit/ZfD74Rs49R3Mii843cHaV/AL1+koPjHRqoRqp/O5Xop+IY HatrCANDJ0ENFXrk47tFMf5fUE68FjePm7nK3ev6DUybXTPgLLHmaGFUanWChIAS oJnXQWVXL6JV9YPvqvzKpyODM= Received: from czl-pc (unknown []) by gzga-smtp-mtada-g0-4 (Coremail) with SMTP id _____wCX0Fr7Iohq8umKRA--.44781S3; Fri, 21 Aug 2026 18:05:49 +0800 (CST) From: Chi Zhiling To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Namjae Jeon , Sungjong Seo , Yuezhang Mo , Chi Zhiling Subject: [RFC PATCH v1 1/6] exfat: remove dead hint_bmap updates in I/O and truncate paths Date: Fri, 21 Aug 2026 18:05:26 +0800 Message-ID: <20260821100531.998196-2-chizhiling@163.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821100531.998196-1-chizhiling@163.com> References: <20260821100531.998196-1-chizhiling@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCX0Fr7Iohq8umKRA--.44781S3 X-Coremail-Antispam: 1Uf129KBjvJXoW7uFy7CFykZr4kXr1Duw1xKrg_yoW8Aw43pr s3Gay8KanxXa4UuF409r4DZa4ay3Z3GFWDXFWIkryUJr9Iyr1F9FWjyFyUua1UGw4rury2 qFy5Wr1UWrnxGrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UNL0OUUUUU= X-CM-SenderInfo: hfkl6xxlol0wi6rwjhhfrp/xtbC+B2EImqIIv3VYgAA3J Content-Type: text/plain; charset="utf-8" From: Chi Zhiling hint_bmap is only consumed by exfat_readdir() during directory iteration. exfat_map_cluster() runs on the file I/O path (via iomap) and never reaches directory iteration, and __exfat_truncate() only resets the hint when the inode is already being evicted, so drop them along with the now-unused local_clu_offset. Signed-off-by: Chi Zhiling --- fs/exfat/file.c | 4 ---- fs/exfat/inode.c | 5 ----- 2 files changed, 9 deletions(-) diff --git a/fs/exfat/file.c b/fs/exfat/file.c index a2a9ee1a2004..29c5db12288e 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -278,10 +278,6 @@ int __exfat_truncate(struct inode *inode) /* clear exfat cache */ exfat_cache_inval_inode(inode); =20 - /* hint information */ - ei->hint_bmap.off =3D EXFAT_EOF_CLUSTER; - ei->hint_bmap.clu =3D EXFAT_EOF_CLUSTER; - /* hint_stat will be used if this is directory. */ ei->hint_stat.eidx =3D 0; ei->hint_stat.clu =3D ei->start_clu; diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c index ccd13630187e..d041f893b1c3 100644 --- a/fs/exfat/inode.c +++ b/fs/exfat/inode.c @@ -144,7 +144,6 @@ int exfat_map_cluster(struct inode *inode, unsigned int= clu_offset, struct super_block *sb =3D inode->i_sb; struct exfat_sb_info *sbi =3D EXFAT_SB(sb); struct exfat_inode_info *ei =3D EXFAT_I(inode); - unsigned int local_clu_offset =3D clu_offset; unsigned int num_to_be_allocated =3D 0, num_clusters; =20 num_clusters =3D exfat_bytes_to_cluster(sbi, exfat_ondisk_size(inode)); @@ -234,10 +233,6 @@ int exfat_map_cluster(struct inode *inode, unsigned in= t clu_offset, *balloc =3D true; } =20 - /* hint information */ - ei->hint_bmap.off =3D local_clu_offset; - ei->hint_bmap.clu =3D *clu; - return 0; } =20 --=20 2.53.0 From nobody Mon Sep 28 13:17:34 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB9684756DE for ; Fri, 21 Aug 2026 10:06:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306822; cv=none; b=WoTPnKA0GRHjWn+kTGvDERcJi3KLkaCwWpcCE4BLSghEJLmcE1l6KckvoQ1jXEUVn9S6QUhjGhzEHKB86dJFxojo3PpUE41dLkRY5MGTsEl004J6FyHCIPUo8g/y/I93Y6BQytAWbRxG51QoVmXMyLkmldEeLbOM/fjZHAHfUA4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306822; c=relaxed/simple; bh=cnASTI9NNDIyMBrS9UbkW6KwsdVmhRG/vfKSuXvT0Dk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=axYazzwp/0ZaHESozZ4nwpAj3TTeGt5P50EBRR4M++VAsthaeNhyQ1oyGFjcoNeGuieQPJE0DM18oEI19x85rUWJAOEGCIXXkmZhHLCbUyoIebnlS9thZ2H1xC2TyLUgEmzPMAaGKsF+Tx03/rilg+Q4ilgD8n2fn5oJdus5VoE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=kNt/gR5x; arc=none smtp.client-ip=117.135.210.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="kNt/gR5x" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=gs BZVl/kxpcbYTSjyC0Bseh+Wstyc+ghmPRTAJECPVE=; b=kNt/gR5xfQIMueqH48 l0/r8PrXjr/2XK/JhguJKudv2jJpMFfG3NwmO/rwkOknO6raOBMsFLLKZYd+6Kb3 hZZSIDZHuZGxA+f67V0ZjaQKaGWmZ2YFaevuN4lMX0zz0ycOLBPCKIQ2QoYw1XaC 8pOvIqcPVIqK1v49zAn1gmZAU= Received: from czl-pc (unknown []) by gzga-smtp-mtada-g0-4 (Coremail) with SMTP id _____wCX0Fr7Iohq8umKRA--.44781S4; Fri, 21 Aug 2026 18:05:49 +0800 (CST) From: Chi Zhiling To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Namjae Jeon , Sungjong Seo , Yuezhang Mo , Chi Zhiling Subject: [RFC PATCH v1 2/6] exfat: take bitmap_lock at the start of exfat_alloc_cluster() Date: Fri, 21 Aug 2026 18:05:27 +0800 Message-ID: <20260821100531.998196-3-chizhiling@163.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821100531.998196-1-chizhiling@163.com> References: <20260821100531.998196-1-chizhiling@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCX0Fr7Iohq8umKRA--.44781S4 X-Coremail-Antispam: 1Uf129KBjvJXoW7tFyftF15ZFWrXrWkWr18Grg_yoW8Wry7pr 47Ca45GrZ5Xan7WF4UKrn5Zr1ruw4kWw45JrW3J3WjyFn0yrsY9r9FqF15Za1jkw4xJanF qryYgw4ruanFka7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jDtxfUUUUU= X-CM-SenderInfo: hfkl6xxlol0wi6rwjhhfrp/xtbC2x2EImqIIv3BLwAA3z Content-Type: text/plain; charset="utf-8" From: Chi Zhiling Acquire sbi->bitmap_lock at the top of exfat_alloc_cluster() so the used_clusters/clu_srch_ptr validation and updates are covered by the lock, removing a window where the early checks raced with concurrent allocations. Signed-off-by: Chi Zhiling --- fs/exfat/fatent.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c index a8b11e2ce43f..2db959669563 100644 --- a/fs/exfat/fatent.c +++ b/fs/exfat/fatent.c @@ -427,19 +427,22 @@ int exfat_alloc_cluster(struct inode *inode, unsigned= int num_alloc, struct super_block *sb =3D inode->i_sb; struct exfat_sb_info *sbi =3D EXFAT_SB(sb); =20 + mutex_lock(&sbi->bitmap_lock); + total_cnt =3D EXFAT_DATA_CLUSTER_COUNT(sbi); =20 if (unlikely(total_cnt < sbi->used_clusters)) { exfat_fs_error_ratelimit(sb, "%s: invalid used clusters(t:%u,u:%u)\n", __func__, total_cnt, sbi->used_clusters); - return -EIO; + ret =3D -EIO; + goto unlock; } =20 - if (num_alloc > total_cnt - sbi->used_clusters) - return -ENOSPC; - - mutex_lock(&sbi->bitmap_lock); + if (num_alloc > total_cnt - sbi->used_clusters) { + ret =3D -ENOSPC; + goto unlock; + } =20 hint_clu =3D p_chain->dir; /* find new cluster */ @@ -516,8 +519,8 @@ int exfat_alloc_cluster(struct inode *inode, unsigned i= nt num_alloc, done: sbi->clu_srch_ptr =3D hint_clu; sbi->used_clusters +=3D p_chain->size; - mutex_unlock(&sbi->bitmap_lock); - return 0; + ret =3D 0; + goto unlock; } =20 hint_clu =3D new_clu + 1; --=20 2.53.0 From nobody Mon Sep 28 13:17:34 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E566346F483 for ; Fri, 21 Aug 2026 10:06:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306815; cv=none; b=Ynk8chS+w97GbafRp3BxMj0zDr+zC0WqpxiQHh+8p61/Gnf2KctiaPT7wf6rard5gk7cvuliVIlO1NDmFwLCQ6XPCQU2LnNrJwNw8aTtJ/0f8TMVbkNdJJl8zlMc20LIVj+IzibQEvgLQy2yAHjcATA1I0xRNR2rtiI0N/ljfpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306815; c=relaxed/simple; bh=2RsmOyichIyZPhhyF8xkhB/QBWU7fplblmFqj5PVJiE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SmGSZwrMU0xxVHzJEGfX+ts1GwVjQxFz49c+L/Ucn0O3cSmKC4orzZYErAdjoF4MlOp65j52KQsIPgQFTTAQXrgoK2XQSmbmDV9kFqC7bveRb3Il4T2ydfzjaHMApVfRWIru1VCaZcpatM6vXuJCVQTW0ial3l9CmG3a7hYsO4o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=KZnglMo/; arc=none smtp.client-ip=220.197.31.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="KZnglMo/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=u/ hnK46qkikKl7QWKcVhN2hitJ+i2z3Li5CjKXAsqz0=; b=KZnglMo/1ScN61pXty hDP83Kt2CBHPQjchlxn/TYph/SUwy2IWC4YuExf5y49kQmWzfu//Y3Ac8G+b9llj OcvBCGZFJGyx5qkeWfIuYwHR4Avn9AJVW98JkZZkn+8px+ftCGkDb9+0ZeIG3N5h edmDQslS2guQQvhr25HatnZ54= Received: from czl-pc (unknown []) by gzga-smtp-mtada-g0-4 (Coremail) with SMTP id _____wCX0Fr7Iohq8umKRA--.44781S5; Fri, 21 Aug 2026 18:05:49 +0800 (CST) From: Chi Zhiling To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Namjae Jeon , Sungjong Seo , Yuezhang Mo , Chi Zhiling Subject: [RFC PATCH v1 3/6] exfat: use atomic bit ops for volume dirty flag Date: Fri, 21 Aug 2026 18:05:28 +0800 Message-ID: <20260821100531.998196-4-chizhiling@163.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821100531.998196-1-chizhiling@163.com> References: <20260821100531.998196-1-chizhiling@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCX0Fr7Iohq8umKRA--.44781S5 X-Coremail-Antispam: 1Uf129KBjvJXoWxurykZF45KF4kWr18WF15urg_yoWrtw4fpF 4kKayrKayUt3WUXw4DJrs8AayfC34xWay3Cryfu34Dtry3G3W0vry8ta4SvF15Xwn7C3Wj qas0yrn5uFnrGFUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jlHqcUUUUU= X-CM-SenderInfo: hfkl6xxlol0wi6rwjhhfrp/xtbC9x2EImqIIv3hpQAA31 Content-Type: text/plain; charset="utf-8" From: Chi Zhiling After converting s_lock to a reader-writer lock, multiple operations can execute concurrently under the read lock. As a result, multiple threads may concurrently update sbi->vol_flags, causing a race in the existing read-modify-write sequence. Convert sbi->vol_flags to an unsigned long bitmap and use test_and_set_bit() / test_and_clear_bit() to atomically update the volume dirty bit. Only the thread performing the 0 -> 1 transition updates the boot sector, avoiding concurrent unsynchronized modifications of vol_flags and the boot-sector buffer. Remove vol_flags_persistent, since the bitmap can directly retain the MEDIA_FAILURE state while preserving the complete 16-bit on-disk volume flags field when writing it back. Signed-off-by: Chi Zhiling --- fs/exfat/exfat_fs.h | 3 +-- fs/exfat/exfat_raw.h | 4 ++-- fs/exfat/super.c | 28 ++++++++++++---------------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index a9131fe03302..f1505c013248 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -232,8 +232,7 @@ struct exfat_sb_info { unsigned int num_FAT_sectors; /* num of FAT sectors */ unsigned int root_dir; /* root dir cluster */ unsigned int dentries_per_clu; /* num of dentries per cluster */ - unsigned int vol_flags; /* volume flags */ - unsigned int vol_flags_persistent; /* volume flags to retain */ + unsigned long vol_flags; /* volume flags (bitmap) */ struct buffer_head *boot_bh; /* buffer_head of BOOT sector */ =20 unsigned int map_clu; /* allocation bitmap start cluster */ diff --git a/fs/exfat/exfat_raw.h b/fs/exfat/exfat_raw.h index ec70cd35bba0..222fee5c2adf 100644 --- a/fs/exfat/exfat_raw.h +++ b/fs/exfat/exfat_raw.h @@ -14,8 +14,8 @@ =20 #define EXFAT_MAX_FILE_LEN 255 =20 -#define VOLUME_DIRTY 0x0002 -#define MEDIA_FAILURE 0x0004 +#define VOLUME_DIRTY_BIT 1 +#define MEDIA_FAILURE_BIT 2 =20 #define EXFAT_EOF_CLUSTER 0xFFFFFFFFu #define EXFAT_BAD_CLUSTER 0xFFFFFFF7u diff --git a/fs/exfat/super.c b/fs/exfat/super.c index a9ea36ba2693..491273d8eeb6 100644 --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -69,27 +69,18 @@ static int exfat_statfs(struct dentry *dentry, struct k= statfs *buf) return 0; } =20 -static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_= flags) +static int exfat_sync_vol_flags(struct super_block *sb) { struct exfat_sb_info *sbi =3D EXFAT_SB(sb); struct boot_sector *p_boot =3D (struct boot_sector *)sbi->boot_bh->b_data; =20 - /* retain persistent-flags */ - new_flags |=3D sbi->vol_flags_persistent; - - /* flags are not changed */ - if (sbi->vol_flags =3D=3D new_flags) - return 0; - - sbi->vol_flags =3D new_flags; - /* skip updating volume dirty flag, * if this volume has been mounted with read-only */ if (sb_rdonly(sb)) return 0; =20 - p_boot->vol_flags =3D cpu_to_le16(new_flags); + p_boot->vol_flags =3D cpu_to_le16((unsigned short)READ_ONCE(sbi->vol_flag= s)); =20 set_buffer_uptodate(sbi->boot_bh); mark_buffer_dirty(sbi->boot_bh); @@ -103,14 +94,20 @@ int exfat_set_volume_dirty(struct super_block *sb) { struct exfat_sb_info *sbi =3D EXFAT_SB(sb); =20 - return exfat_set_vol_flags(sb, sbi->vol_flags | VOLUME_DIRTY); + if (test_and_set_bit(VOLUME_DIRTY_BIT, &sbi->vol_flags)) + return 0; + + return exfat_sync_vol_flags(sb); } =20 int exfat_clear_volume_dirty(struct super_block *sb) { struct exfat_sb_info *sbi =3D EXFAT_SB(sb); =20 - return exfat_set_vol_flags(sb, sbi->vol_flags & ~VOLUME_DIRTY); + if (!test_and_clear_bit(VOLUME_DIRTY_BIT, &sbi->vol_flags)) + return 0; + + return exfat_sync_vol_flags(sb); } =20 static int exfat_show_options(struct seq_file *m, struct dentry *root) @@ -509,7 +506,6 @@ static int exfat_read_boot_sector(struct super_block *s= b) (sbi->cluster_size_bits - DENTRY_SIZE_BITS); =20 sbi->vol_flags =3D le16_to_cpu(p_boot->vol_flags); - sbi->vol_flags_persistent =3D sbi->vol_flags & (VOLUME_DIRTY | MEDIA_FAIL= URE); sbi->clu_srch_ptr =3D EXFAT_FIRST_CLUSTER; =20 /* check consistencies */ @@ -526,9 +522,9 @@ static int exfat_read_boot_sector(struct super_block *s= b) return -EINVAL; } =20 - if (sbi->vol_flags & VOLUME_DIRTY) + if (test_bit(VOLUME_DIRTY_BIT, &sbi->vol_flags)) exfat_warn(sb, "Volume was not properly unmounted. Some data may be corr= upt. Please run fsck."); - if (sbi->vol_flags & MEDIA_FAILURE) + if (test_bit(MEDIA_FAILURE_BIT, &sbi->vol_flags)) exfat_warn(sb, "Medium has reported failures. Some data may be lost."); =20 /* --=20 2.53.0 From nobody Mon Sep 28 13:17:34 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2E7E2472549 for ; Fri, 21 Aug 2026 10:06:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306829; cv=none; b=SARYLpeu99zIXAgFLXLgWDcZ4pXfyaDpV99m1X8/+wjYwrq1sfartoxBZHFd7NqA1CdgPDdx4AgdzwuNenhdiw/PEHWxoJ/l4eoXOWGfjhY2bvY8bRxso2Faq/+VbbgcVhvso+ExpmhtFbgXv5lWYF19LqrDc4C4PTKGlN7uPMA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306829; c=relaxed/simple; bh=7b4cthY1+0Q2u/grTK+sXWNz7xCT0Pn4BRzc/YZh2RQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ccyrqu1NNMT1BJI9p11D5EusIbx5Q3VQyku+iIUSELFwrwe8XY+Vh853uvE0PaJ+saV8dxxwIieGyKUS3ReXx2oDYmW+b/JqubU/MQxCJ5G18XseFt1F2Ijd5oGUiAvtzpV1aH5sp0lsI8Z+Nu5r9/N1x7WKhe+y+TA4gcYdRpo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=hQyhK453; arc=none smtp.client-ip=117.135.210.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="hQyhK453" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=t/ 5pUE4Bfaq2HTnv7QgbHtJJrsNc4LPB3ttB7GtLyw4=; b=hQyhK453ZBEQ5h+5l3 IDUU/zFmG/bV8xmA1vmDrVqz6wOzn1ol6MQqKv14TS5psA/8FoQ14hByxsHUYos9 9Q23w2ImCNiSETavM2SQqy87ffd952rirvhf8dJ8vuLBKH4P0VDqaS+uGL4zN9bw TBHgBWGbUtuNHddrmebqp2EPs= Received: from czl-pc (unknown []) by gzga-smtp-mtada-g0-4 (Coremail) with SMTP id _____wCX0Fr7Iohq8umKRA--.44781S6; Fri, 21 Aug 2026 18:05:49 +0800 (CST) From: Chi Zhiling To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Namjae Jeon , Sungjong Seo , Yuezhang Mo , Chi Zhiling Subject: [RFC PATCH v1 4/6] exfat: lock FAT2 buffer while copying mirrored FAT entries Date: Fri, 21 Aug 2026 18:05:29 +0800 Message-ID: <20260821100531.998196-5-chizhiling@163.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821100531.998196-1-chizhiling@163.com> References: <20260821100531.998196-1-chizhiling@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCX0Fr7Iohq8umKRA--.44781S6 X-Coremail-Antispam: 1Uf129KBjvdXoW7JFyfAF4UurWrCFy8uFyDKFg_yoWkCFcE9r 92kay8G3s0yayrJ3WkZF1qqr13Ka18ur18Wry7CFy5W3sFy39xXrWDCr1qkasFya47Xrsx Arn5Wrs0k3WFgjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8Yxn0WfASr-VFAUDa7-sFnT 9fnUUvcSsGvfC2KfnxnUUI43ZEXa7IU0eT5PUUUUU== X-CM-SenderInfo: hfkl6xxlol0wi6rwjhhfrp/xtbC3B2EImqIIv0UmQAA3X Content-Type: text/plain; charset="utf-8" From: Chi Zhiling exfat_mirror_bh() updates the FAT2 buffer without serializing the copy against writeback. Once s_lock is converted to a read-write lock, multiple read-side operations may run concurrently with writeback. This can allow writeback to observe a partially updated FAT2 block. Lock the destination buffer while copying the FAT entry data to serialize the update with writeback and prevent torn FAT2 writes. Signed-off-by: Chi Zhiling --- fs/exfat/fatent.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c index 2db959669563..f6ad2825ad19 100644 --- a/fs/exfat/fatent.c +++ b/fs/exfat/fatent.c @@ -24,7 +24,10 @@ static int exfat_mirror_bh(struct super_block *sb, struc= t buffer_head *bh) c_bh =3D sb_getblk(sb, sec2); if (!c_bh) return -ENOMEM; + /* Serialize the copy with writeback to avoid a torn FAT2 write */ + lock_buffer(c_bh); memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize); + unlock_buffer(c_bh); err =3D exfat_update_bh(c_bh, sb->s_flags & SB_SYNCHRONOUS); brelse(c_bh); } --=20 2.53.0 From nobody Mon Sep 28 13:17:34 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23F453ACEF2 for ; Fri, 21 Aug 2026 10:06:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306822; cv=none; b=pMn7q0k2mIa2Pv7jml94/cmMyqKvPRe8I74q957kVfR9JQQXxUIDKz0t22tJ/xETHIWrV0o+hInH+r41UGti02sYhihILdXXQx5ytuDfN064+T4Jr8vMnfTE8ZqSZUnk+tLU+4wYeBMTbqaa2Makvv1i0XqkJed3hzKY9oB3ixI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306822; c=relaxed/simple; bh=DZWCZO6Bh8geH2F8aW84d2LoIpNDP5+WVIZ7mh9f/5M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Pgfp3khI71EaFxHzyOnxaXYxnD60UmegoRAfkK1E6Atuo6NQqtOGkEpCvxNxXGHQngX+SpNVmku3Yi6YI/+1MUoi5qEdVU9xtxzVDdlKOqmZEY4rCawb39bAVMlMPVL2Miqrb8zK4n60C6GFgFwG3V0w5ttY3nUfOVVybqYddIk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=PLgDbwnV; arc=none smtp.client-ip=117.135.210.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="PLgDbwnV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=le F2pg8mCziAz0+Aqg7R1uG1gLbSEIptaxaNYmSNJMo=; b=PLgDbwnVJKyDXhWOz/ KbbjQqqd26i059kGqVEyMaMug62jcFlDvjduPnOMXPdc0CS+WEeLP5dWcThqOZ2Z OYEud78w/EPxkA+3U0VLC9FFc0G43exvH81UuRQT7cjXcq41v8MjltINhER5PYPl RIAGkpXyQIQP97b9y6oiMh07U= Received: from czl-pc (unknown []) by gzga-smtp-mtada-g0-4 (Coremail) with SMTP id _____wCX0Fr7Iohq8umKRA--.44781S7; Fri, 21 Aug 2026 18:05:50 +0800 (CST) From: Chi Zhiling To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Namjae Jeon , Sungjong Seo , Yuezhang Mo , Chi Zhiling 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 Message-ID: <20260821100531.998196-6-chizhiling@163.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821100531.998196-1-chizhiling@163.com> References: <20260821100531.998196-1-chizhiling@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCX0Fr7Iohq8umKRA--.44781S7 X-Coremail-Antispam: 1Uf129KBjvJXoWfGr1rWFWDKFWkur17uFWrGrg_yoWkWF47pr Z0kayvqr18X3ZrWr4kKF43ZF1Fyw1IgFW7Jryku3ZrAFyqqr129FyjvFy3ZFnYq3yxGwsY gFWj9r45GwsrGrUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07j2uWdUUUUU= X-CM-SenderInfo: hfkl6xxlol0wi6rwjhhfrp/xtbC2x6EImqIIv7BRAAA3Y Content-Type: text/plain; charset="utf-8" From: Chi Zhiling 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 --- 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); =20 if (ei->flags =3D=3D ALLOC_NO_FAT_CHAIN && cpos >=3D i_size_read(inode)) goto end_of_dir; @@ -255,7 +255,7 @@ static int exfat_iterate(struct file *file, struct dir_= context *ctx) inum =3D iunique(sb, EXFAT_ROOT_INO); } =20 - 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 =3D ITER_POS_FILLED_DOTS; ctx->pos =3D 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, s= truct exfat_uni_name *label struct exfat_entry_set_cache es; struct exfat_dentry *ep; =20 - mutex_lock(&sbi->s_lock); + down_write(&sbi->s_lock); =20 memset(label_out, 0, sizeof(*label_out)); ret =3D exfat_get_volume_label_dentry(sb, &es); @@ -1322,7 +1322,7 @@ int exfat_read_volume_label(struct super_block *sb, s= truct exfat_uni_name *label =20 exfat_put_dentry_set(&es, false); unlock: - mutex_unlock(&sbi->s_lock); + up_write(&sbi->s_lock); return ret; } =20 @@ -1339,7 +1339,7 @@ int exfat_write_volume_label(struct super_block *sb, if (label->name_len > EXFAT_VOLUME_LABEL_LEN) return -EINVAL; =20 - mutex_lock(&sbi->s_lock); + down_write(&sbi->s_lock); =20 ret =3D exfat_get_volume_label_dentry(sb, &es); if (ret =3D=3D -ENOENT) { @@ -1376,6 +1376,6 @@ int exfat_write_volume_label(struct super_block *sb, ret =3D exfat_put_dentry_set(&es, IS_DIRSYNC(root_inode)); =20 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 { =20 unsigned long s_exfat_flags; /* Exfat superblock flags */ =20 - 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 =3D EXFAT_I(inode); int err; =20 - mutex_lock(&sbi->s_lock); + down_write(&sbi->s_lock); if (ei->start_clu =3D=3D 0) { /* * Empty start_clu !=3D ~0 (not allocated) @@ -312,7 +312,7 @@ static void exfat_truncate(struct inode *inode) =20 inode->i_blocks =3D round_up(i_size_read(inode), sbi->cluster_size) >> 9; write_size: - mutex_unlock(&sbi->s_lock); + up_write(&sbi->s_lock); } =20 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 wri= teback_control *wbc) if (unlikely(exfat_forced_shutdown(inode->i_sb))) return -EIO; =20 - mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + down_write(&EXFAT_SB(inode->i_sb)->s_lock); ret =3D __exfat_write_inode(inode, wbc->sync_mode =3D=3D WB_SYNC_ALL); - mutex_unlock(&EXFAT_SB(inode->i_sb)->s_lock); + up_write(&EXFAT_SB(inode->i_sb)->s_lock); =20 return ret; } =20 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); } =20 @@ -443,9 +443,9 @@ void exfat_evict_inode(struct inode *inode) =20 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); } =20 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 =3D exfat_bytes_to_cluster_round_up(sbi, offset + length) - exfat_bytes_to_cluster(sbi, offset); =20 - mutex_lock(&sbi->s_lock); + down_write(&sbi->s_lock); iomap->bdev =3D inode->i_sb->s_bdev; iomap->offset =3D offset; =20 @@ -135,7 +135,7 @@ static int __exfat_iomap_begin(struct inode *inode, lof= f_t offset, loff_t length =20 iomap->flags |=3D IOMAP_F_MERGED; out: - mutex_unlock(&sbi->s_lock); + up_write(&sbi->s_lock); return err; } =20 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; =20 - mutex_lock(&EXFAT_SB(sb)->s_lock); + down_write(&EXFAT_SB(sb)->s_lock); exfat_set_volume_dirty(sb); err =3D 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, =20 d_instantiate(dentry, inode); unlock: - mutex_unlock(&EXFAT_SB(sb)->s_lock); + up_write(&EXFAT_SB(sb)->s_lock); return err; } =20 @@ -732,7 +732,7 @@ static struct dentry *exfat_lookup(struct inode *dir, s= truct dentry *dentry, int err; loff_t i_pos; =20 - mutex_lock(&EXFAT_SB(sb)->s_lock); + down_write(&EXFAT_SB(sb)->s_lock); err =3D exfat_find(dir, &dentry->d_name, &info); if (err) { if (unlikely(err !=3D -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)); =20 @@ -785,7 +785,7 @@ static int exfat_unlink(struct inode *dir, struct dentr= y *dentry) if (unlikely(exfat_forced_shutdown(sb))) return -EIO; =20 - mutex_lock(&EXFAT_SB(sb)->s_lock); + down_write(&EXFAT_SB(sb)->s_lock); if (ei->dir.dir =3D=3D DIR_DELETED) { exfat_err(sb, "abnormal access to deleted dentry"); err =3D -ENOENT; @@ -821,7 +821,7 @@ static int exfat_unlink(struct inode *dir, struct dentr= y *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; } =20 @@ -838,7 +838,7 @@ static struct dentry *exfat_mkdir(struct mnt_idmap *idm= ap, struct inode *dir, if (unlikely(exfat_forced_shutdown(sb))) return ERR_PTR(-EIO); =20 - mutex_lock(&EXFAT_SB(sb)->s_lock); + down_write(&EXFAT_SB(sb)->s_lock); exfat_set_volume_dirty(sb); err =3D 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 *idm= ap, struct inode *dir, d_instantiate(dentry, inode); =20 unlock: - mutex_unlock(&EXFAT_SB(sb)->s_lock); + up_write(&EXFAT_SB(sb)->s_lock); return err ? ERR_PTR(err) : NULL; } =20 @@ -929,7 +929,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry= *dentry) if (unlikely(exfat_forced_shutdown(sb))) return -EIO; =20 - mutex_lock(&EXFAT_SB(inode->i_sb)->s_lock); + down_write(&EXFAT_SB(inode->i_sb)->s_lock); =20 if (ei->dir.dir =3D=3D 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; } =20 @@ -1282,7 +1282,7 @@ static int exfat_rename(struct mnt_idmap *idmap, if (flags & ~RENAME_NOREPLACE) return -EINVAL; =20 - mutex_lock(&EXFAT_SB(sb)->s_lock); + down_write(&EXFAT_SB(sb)->s_lock); old_inode =3D old_dentry->d_inode; new_inode =3D new_dentry->d_inode; =20 @@ -1334,7 +1334,7 @@ static int exfat_rename(struct mnt_idmap *idmap, } =20 unlock: - mutex_unlock(&EXFAT_SB(sb)->s_lock); + up_write(&EXFAT_SB(sb)->s_lock); return err; } =20 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 =3D EXFAT_SB(sb); =20 - 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); } =20 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 |=3D SB_NODIRATIME; =20 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); =20 if (new_opts->allow_utime =3D=3D (unsigned short)-1) new_opts->allow_utime =3D ~new_opts->fs_dmask & 0022; @@ -820,7 +820,7 @@ static int exfat_init_fs_context(struct fs_context *fc) if (!sbi) return -ENOMEM; =20 - 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); --=20 2.53.0 From nobody Mon Sep 28 13:17:34 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 42AE539BFFE for ; Fri, 21 Aug 2026 10:06:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306827; cv=none; b=Bo3Bn/SugNGvu4XwT1emtDZN+0nhvP5JHQZlkYmYrx02EHpb39MloDhZdQuSQjHWx41umkb1FBlEP7pSrqkP2ZnvT1wLYBBOFx6ipfkbk5VtRr2ogXfj4BJQXAbQWeWtnTnUhNLZe73PAzHcSFhLGvjLtct88Z/K7JHE0bkvOwk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787306827; c=relaxed/simple; bh=Rg8aNP+GmG8riZKg5ALm97SxNozAbxyKD/6Sl9MeRm8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PGVRYzd1T1Zm41InEMZk/Q4k0053Nq2Tzp/GwOFE+rxaEvcWJUa3w7bPmf+nswB8VPG52TZMLOsV7wmCvEIXCkBaI6o3BjhxQA0lugukYllP4K3axO5f9UEBNGdDfAXKcSLuvXiOWDUdN8VuC2lXDOdYSCOPD5ekhmlzHVjtius= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=jwivui1S; arc=none smtp.client-ip=220.197.31.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="jwivui1S" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=45 e0F3JYLMADVB/74KsXUhFkkD4nJlLfZ7gO7cpyAb0=; b=jwivui1SxLivomLwDU cxb9TX22Ke/QcKap7EyX6TXBzETyF3zFYR9+d3C7pw0eWl2reSVX7+jPQmbYhmxZ UDCjep3O4Gs2BKMriAF1d2N3V5Wqtf8cQHnZdY1FZ/SRMUsSMunxi/i0pZB4t4tn p7/ArRp0NyGC95sPELmI8Y9V8= Received: from czl-pc (unknown []) by gzga-smtp-mtada-g0-4 (Coremail) with SMTP id _____wCX0Fr7Iohq8umKRA--.44781S8; Fri, 21 Aug 2026 18:05:50 +0800 (CST) From: Chi Zhiling To: exfat@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Namjae Jeon , Sungjong Seo , Yuezhang Mo , Chi Zhiling Subject: [RFC PATCH v1 6/6] exfat: take s_lock in read mode for iomap mapping paths Date: Fri, 21 Aug 2026 18:05:31 +0800 Message-ID: <20260821100531.998196-7-chizhiling@163.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821100531.998196-1-chizhiling@163.com> References: <20260821100531.998196-1-chizhiling@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCX0Fr7Iohq8umKRA--.44781S8 X-Coremail-Antispam: 1Uf129KBjvJXoWxAF1xtr1Dtry5WFy7WF18uFg_yoW5Gw43pa 95Ka13Kr4UX3W7WF4kGFsYvF1Fkws3KF47JF18G3ZIv39Ivr10vFy09Fy3Zw15Xw1xGr4q qFWYgr4Uur1fCF7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07j2XdUUUUUU= X-CM-SenderInfo: hfkl6xxlol0wi6rwjhhfrp/xtbC3B6EImqIIv4UpQAA3r Content-Type: text/plain; charset="utf-8" From: Chi Zhiling The iomap mapping paths mainly access the FAT chain of the file itself. Concurrent mappings of distinct inodes can therefore proceed in parallel by taking s_lock in read mode instead of write mode. The superblock-wide state shared between files is already protected by the preceding patches: the allocation bitmap, used_clusters and clu_srch_ptr by bitmap_lock, and the volume dirty flag / boot sector by atomic bit ops with a single writer on the 0 -> 1 transition. Concurrent access to the same inode stays serialized by the exclusive inode_lock held in exfat_file_write_iter(). Writeback takes the read lock even though it does not hold inode_lock. Folios under writeback are marked writeback, and truncate first flushes and truncates the page cache, so truncate cannot run concurrently with writeback. Writeback therefore only maps clusters that are still committed or owned by the inode and cannot race with cluster freeing. The lock ordering remains inode_lock -> s_lock -> bitmap_lock, so this change does not introduce any new deadlock scenarios. Signed-off-by: Chi Zhiling --- fs/exfat/iomap.c | 4 ++-- fs/exfat/super.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/exfat/iomap.c b/fs/exfat/iomap.c index bc8bdfa9bb80..147e9da01a47 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 =3D exfat_bytes_to_cluster_round_up(sbi, offset + length) - exfat_bytes_to_cluster(sbi, offset); =20 - down_write(&sbi->s_lock); + down_read(&sbi->s_lock); iomap->bdev =3D inode->i_sb->s_bdev; iomap->offset =3D offset; =20 @@ -135,7 +135,7 @@ static int __exfat_iomap_begin(struct inode *inode, lof= f_t offset, loff_t length =20 iomap->flags |=3D IOMAP_F_MERGED; out: - up_write(&sbi->s_lock); + up_read(&sbi->s_lock); return err; } =20 diff --git a/fs/exfat/super.c b/fs/exfat/super.c index 72a35f4079b4..64ec4d2d1bf6 100644 --- a/fs/exfat/super.c +++ b/fs/exfat/super.c @@ -94,6 +94,8 @@ int exfat_set_volume_dirty(struct super_block *sb) { struct exfat_sb_info *sbi =3D EXFAT_SB(sb); =20 + lockdep_assert_held(&sbi->s_lock); + if (test_and_set_bit(VOLUME_DIRTY_BIT, &sbi->vol_flags)) return 0; =20 @@ -104,6 +106,8 @@ int exfat_clear_volume_dirty(struct super_block *sb) { struct exfat_sb_info *sbi =3D EXFAT_SB(sb); =20 + lockdep_assert_held_write(&sbi->s_lock); + if (!test_and_clear_bit(VOLUME_DIRTY_BIT, &sbi->vol_flags)) return 0; =20 --=20 2.53.0