* [PATCH v1 1/6] exfat: fix incorrect directory checksum after rename to shorter name
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
@ 2026-03-31 9:11 ` Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 2/6] exfat: introduce exfat_fat_walk helper Chi Zhiling
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-03-31 9:11 UTC (permalink / raw)
To: Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, Chi Zhiling
From: Chi Zhiling <chizhiling@kylinos.cn>
When renaming a file in-place to a shorter name, exfat_remove_entries
marks excess entries as DELETED, but es->num_entries is not updated
accordingly. As a result, exfat_update_dir_chksum iterates over the
deleted entries and computes an incorrect checksum.
This does not lead to persistent corruption because mark_inode_dirty()
is called afterward, and __exfat_write_inode later recomputes the
checksum using the correct num_entries value.
Fix by setting es->num_entries = num_entries in exfat_init_ext_entry.
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
fs/exfat/dir.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index a2c2b998808c..7619410d668e 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -490,6 +490,7 @@ void exfat_init_ext_entry(struct exfat_entry_set_cache *es, int num_entries,
unsigned short *uniname = p_uniname->name;
struct exfat_dentry *ep;
+ es->num_entries = num_entries;
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
ep->dentry.file.num_ext = (unsigned char)(num_entries - 1);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v1 2/6] exfat: introduce exfat_fat_walk helper
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 1/6] exfat: fix incorrect directory checksum after rename to shorter name Chi Zhiling
@ 2026-03-31 9:11 ` Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 3/6] exfat: use exfat_fat_walk helper to simplify fat entry walking Chi Zhiling
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-03-31 9:11 UTC (permalink / raw)
To: Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, Chi Zhiling
From: Chi Zhiling <chizhiling@kylinos.cn>
Introduce exfat_fat_walk() to walk the FAT chain by a given step,
handling both ALLOC_NO_FAT_CHAIN and ALLOC_FAT_CHAIN modes. Also
redefine exfat_get_next_cluster as a thin wrapper around it for
backward compatibility.
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
fs/exfat/exfat_fs.h | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 9fed9fb33cae..530459ab9acc 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -437,7 +437,8 @@ int exfat_set_volume_dirty(struct super_block *sb);
int exfat_clear_volume_dirty(struct super_block *sb);
/* fatent.c */
-#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu, NULL)
+#define exfat_get_next_cluster(sb, pclu) \
+ exfat_fat_walk(sb, (pclu), 1, ALLOC_FAT_CHAIN)
int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
struct exfat_chain *p_chain, bool sync_bmap);
@@ -456,6 +457,26 @@ int exfat_count_num_clusters(struct super_block *sb,
int exfat_blk_readahead(struct super_block *sb, sector_t sec,
sector_t *ra, blkcnt_t *ra_cnt, sector_t end);
+static inline int
+exfat_fat_walk(struct super_block *sb, unsigned int *clu,
+ unsigned int step, int flags)
+{
+ struct buffer_head *bh = NULL;
+
+ if (flags == ALLOC_NO_FAT_CHAIN) {
+ (*clu) += step;
+ return 0;
+ }
+
+ while (step--) {
+ if (exfat_ent_get(sb, *clu, clu, &bh))
+ return -EIO;
+ }
+ brelse(bh);
+
+ return 0;
+}
+
/* balloc.c */
int exfat_load_bitmap(struct super_block *sb);
void exfat_free_bitmap(struct exfat_sb_info *sbi);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v1 3/6] exfat: use exfat_fat_walk helper to simplify fat entry walking
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 1/6] exfat: fix incorrect directory checksum after rename to shorter name Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 2/6] exfat: introduce exfat_fat_walk helper Chi Zhiling
@ 2026-03-31 9:11 ` Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 4/6] exfat: remove NULL cache pointer case in exfat_ent_get Chi Zhiling
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-03-31 9:11 UTC (permalink / raw)
To: Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, Chi Zhiling
From: Chi Zhiling <chizhiling@kylinos.cn>
Replace the custom exfat_walk_fat_chain() function and open-coded
FAT chain walking logic with the exfat_fat_walk() helper across
exfat_find_location, __exfat_get_dentry_set, and exfat_map_cluster.
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
fs/exfat/dir.c | 39 +++------------------------------------
fs/exfat/inode.c | 11 ++---------
2 files changed, 5 insertions(+), 45 deletions(-)
diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index 7619410d668e..cfc6f16a5fb2 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -562,38 +562,6 @@ int exfat_put_dentry_set(struct exfat_entry_set_cache *es, int sync)
return err;
}
-static int exfat_walk_fat_chain(struct super_block *sb,
- struct exfat_chain *p_dir, unsigned int byte_offset,
- unsigned int *clu)
-{
- struct exfat_sb_info *sbi = EXFAT_SB(sb);
- unsigned int clu_offset;
- unsigned int cur_clu;
-
- clu_offset = EXFAT_B_TO_CLU(byte_offset, sbi);
- cur_clu = p_dir->dir;
-
- if (p_dir->flags == ALLOC_NO_FAT_CHAIN) {
- cur_clu += clu_offset;
- } else {
- while (clu_offset > 0) {
- if (exfat_get_next_cluster(sb, &cur_clu))
- return -EIO;
- if (cur_clu == EXFAT_EOF_CLUSTER) {
- exfat_fs_error(sb,
- "invalid dentry access beyond EOF (clu : %u, eidx : %d)",
- p_dir->dir,
- EXFAT_B_TO_DEN(byte_offset));
- return -EIO;
- }
- clu_offset--;
- }
- }
-
- *clu = cur_clu;
- return 0;
-}
-
static int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir,
int entry, sector_t *sector, int *offset)
{
@@ -603,7 +571,8 @@ static int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir
off = EXFAT_DEN_TO_B(entry);
- ret = exfat_walk_fat_chain(sb, p_dir, off, &clu);
+ clu = p_dir->dir;
+ ret = exfat_fat_walk(sb, &clu, EXFAT_B_TO_CLU(off, sbi), p_dir->flags);
if (ret)
return ret;
@@ -792,9 +761,7 @@ static int __exfat_get_dentry_set(struct exfat_entry_set_cache *es,
if (exfat_is_last_sector_in_cluster(sbi, sec)) {
unsigned int clu = exfat_sector_to_cluster(sbi, sec);
- if (p_dir->flags == ALLOC_NO_FAT_CHAIN)
- clu++;
- else if (exfat_get_next_cluster(sb, &clu))
+ if (exfat_fat_walk(sb, &clu, 1, p_dir->flags))
goto put_es;
sec = exfat_cluster_to_sector(sbi, clu);
} else {
diff --git a/fs/exfat/inode.c b/fs/exfat/inode.c
index beb9ea7cca9f..817d9a135bb6 100644
--- a/fs/exfat/inode.c
+++ b/fs/exfat/inode.c
@@ -225,15 +225,8 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
* *clu = (the first cluster of the allocated chain) =>
* (the last cluster of ...)
*/
- if (ei->flags == ALLOC_NO_FAT_CHAIN) {
- *clu += num_to_be_allocated - 1;
- } else {
- while (num_to_be_allocated > 1) {
- if (exfat_get_next_cluster(sb, clu))
- return -EIO;
- num_to_be_allocated--;
- }
- }
+ if (exfat_fat_walk(sb, clu, num_to_be_allocated - 1, ei->flags))
+ return -EIO;
*count = 1;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v1 4/6] exfat: remove NULL cache pointer case in exfat_ent_get
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
` (2 preceding siblings ...)
2026-03-31 9:11 ` [PATCH v1 3/6] exfat: use exfat_fat_walk helper to simplify fat entry walking Chi Zhiling
@ 2026-03-31 9:11 ` Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 5/6] exfat: introduce exfat_chain_advance helper Chi Zhiling
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-03-31 9:11 UTC (permalink / raw)
To: Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, Chi Zhiling
From: Chi Zhiling <chizhiling@kylinos.cn>
Since exfat_get_next_cluster has been updated, no callers pass a NULL
pointer to exfat_ent_get, so remove the handling logic for this case.
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
fs/exfat/fatent.c | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c
index f2e5d5dde393..dce0955e689a 100644
--- a/fs/exfat/fatent.c
+++ b/fs/exfat/fatent.c
@@ -44,11 +44,11 @@ static int exfat_end_bh(struct super_block *sb, struct buffer_head *bh)
}
static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
- unsigned int *content, struct buffer_head **last)
+ unsigned int *content, struct buffer_head **cache)
{
unsigned int off;
sector_t sec;
- struct buffer_head *bh = last ? *last : NULL;
+ struct buffer_head *bh = *cache;
sec = FAT_ENT_OFFSET_SECTOR(sb, loc);
off = FAT_ENT_OFFSET_BYTE_IN_SECTOR(sb, loc);
@@ -56,8 +56,7 @@ static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
if (!bh || bh->b_blocknr != sec || !buffer_uptodate(bh)) {
brelse(bh);
bh = sb_bread(sb, sec);
- if (last)
- *last = bh;
+ *cache = bh;
if (unlikely(!bh))
return -EIO;
}
@@ -68,8 +67,6 @@ static int __exfat_ent_get(struct super_block *sb, unsigned int loc,
if (*content > EXFAT_BAD_CLUSTER)
*content = EXFAT_EOF_CLUSTER;
- if (!last)
- brelse(bh);
return 0;
}
@@ -111,7 +108,7 @@ int exfat_ent_set(struct super_block *sb, unsigned int loc,
* Caller must release the buffer_head if no error return.
*/
int exfat_ent_get(struct super_block *sb, unsigned int loc,
- unsigned int *content, struct buffer_head **last)
+ unsigned int *content, struct buffer_head **cache)
{
struct exfat_sb_info *sbi = EXFAT_SB(sb);
@@ -122,7 +119,7 @@ int exfat_ent_get(struct super_block *sb, unsigned int loc,
goto err;
}
- if (unlikely(__exfat_ent_get(sb, loc, content, last))) {
+ if (unlikely(__exfat_ent_get(sb, loc, content, cache))) {
exfat_fs_error_ratelimit(sb,
"failed to access to FAT (entry 0x%08x)",
loc);
@@ -151,13 +148,11 @@ int exfat_ent_get(struct super_block *sb, unsigned int loc,
}
return 0;
-err:
- if (last) {
- brelse(*last);
- /* Avoid double release */
- *last = NULL;
- }
+err:
+ /* Avoid double release */
+ brelse(*cache);
+ *cache = NULL;
return -EIO;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v1 5/6] exfat: introduce exfat_chain_advance helper
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
` (3 preceding siblings ...)
2026-03-31 9:11 ` [PATCH v1 4/6] exfat: remove NULL cache pointer case in exfat_ent_get Chi Zhiling
@ 2026-03-31 9:11 ` Chi Zhiling
2026-03-31 9:11 ` [PATCH v1 6/6] exfat: use " Chi Zhiling
2026-03-31 15:27 ` [syzbot ci] Re: exfat: unify FAT chain walking helpers syzbot ci
6 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-03-31 9:11 UTC (permalink / raw)
To: Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, Chi Zhiling
From: Chi Zhiling <chizhiling@kylinos.cn>
Introduce exfat_chain_advance() to walk a exfat_chain structure by a
given step, updating both ->dir and ->size fields atomically. This
helper handles both ALLOC_NO_FAT_CHAIN and ALLOC_FAT_CHAIN modes with
proper boundary checking.
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
fs/exfat/exfat_fs.h | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 530459ab9acc..d7f88a326cf0 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -552,6 +552,32 @@ int exfat_read_volume_label(struct super_block *sb,
int exfat_write_volume_label(struct super_block *sb,
struct exfat_uni_name *label);
+static inline int exfat_chain_advance(struct super_block *sb,
+ struct exfat_chain *chain, unsigned int step)
+{
+ if (chain->flags == ALLOC_NO_FAT_CHAIN) {
+ if (chain->size > step) {
+ chain->dir += step;
+ chain->size -= step;
+ } else if (chain->size == step) {
+ chain->dir = EXFAT_EOF_CLUSTER;
+ chain->size = 0;
+ } else {
+ return -EIO;
+ }
+ } else {
+ if (exfat_fat_walk(sb, &chain->dir, step, ALLOC_FAT_CHAIN))
+ return -EIO;
+ if (chain->size > step) {
+ chain->size -= step;
+ } else {
+ chain->size = 0;
+ WARN_ON_ONCE(chain->dir != EXFAT_EOF_CLUSTER);
+ }
+ }
+ return 0;
+}
+
/* inode.c */
extern const struct inode_operations exfat_file_inode_operations;
void exfat_sync_inode(struct inode *inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v1 6/6] exfat: use exfat_chain_advance helper
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
` (4 preceding siblings ...)
2026-03-31 9:11 ` [PATCH v1 5/6] exfat: introduce exfat_chain_advance helper Chi Zhiling
@ 2026-03-31 9:11 ` Chi Zhiling
2026-03-31 15:27 ` [syzbot ci] Re: exfat: unify FAT chain walking helpers syzbot ci
6 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-03-31 9:11 UTC (permalink / raw)
To: Namjae Jeon, Sungjong Seo, Yuezhang Mo
Cc: linux-fsdevel, linux-kernel, Chi Zhiling
From: Chi Zhiling <chizhiling@kylinos.cn>
Replace open-coded cluster chain walking logic with exfat_chain_advance()
across exfat_readdir, exfat_find_dir_entry, exfat_count_dir_entries,
exfat_search_empty_slot and exfat_check_dir_empty.
Signed-off-by: Chi Zhiling <chizhiling@kylinos.cn>
---
fs/exfat/dir.c | 71 ++++++++++++------------------------------------
fs/exfat/namei.c | 29 +++++---------------
2 files changed, 25 insertions(+), 75 deletions(-)
diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index cfc6f16a5fb2..adc79694373a 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -93,25 +93,19 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
clu_offset = EXFAT_DEN_TO_CLU(dentry, sbi);
exfat_chain_dup(&clu, &dir);
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- clu.dir += clu_offset;
- clu.size -= clu_offset;
- } else {
+ if (clu.flags == ALLOC_FAT_CHAIN) {
/* hint_information */
if (clu_offset > 0 && ei->hint_bmap.off != EXFAT_EOF_CLUSTER &&
ei->hint_bmap.off > 0 && clu_offset >= ei->hint_bmap.off) {
clu_offset -= ei->hint_bmap.off;
clu.dir = ei->hint_bmap.clu;
- }
-
- while (clu_offset > 0 && clu.dir != EXFAT_EOF_CLUSTER) {
- if (exfat_get_next_cluster(sb, &(clu.dir)))
- return -EIO;
-
- clu_offset--;
+ clu.size -= ei->hint_bmap.off;
}
}
+ if (exfat_chain_advance(sb, &clu, clu_offset))
+ return -EIO;
+
while (clu.dir != EXFAT_EOF_CLUSTER && dentry < max_dentries) {
i = dentry & (dentries_per_clu - 1);
@@ -160,15 +154,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
return 0;
}
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- if (--clu.size > 0)
- clu.dir++;
- else
- clu.dir = EXFAT_EOF_CLUSTER;
- } else {
- if (exfat_get_next_cluster(sb, &(clu.dir)))
- return -EIO;
- }
+ if (exfat_chain_advance(sb, &clu, 1))
+ return -EIO;
}
out:
@@ -1077,19 +1064,12 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
step = DIRENT_STEP_FILE;
}
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- if (--clu.size > 0)
- clu.dir++;
- else
- clu.dir = EXFAT_EOF_CLUSTER;
- } else {
- if (exfat_get_next_cluster(sb, &clu.dir))
- return -EIO;
+ if (exfat_chain_advance(sb, &clu, 1))
+ return -EIO;
+ /* break if the cluster chain includes a loop */
+ if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
+ goto not_found;
- /* break if the cluster chain includes a loop */
- if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
- goto not_found;
- }
}
not_found:
@@ -1124,14 +1104,7 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
if (!((dentry + 1) & (dentries_per_clu - 1))) {
int ret = 0;
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- if (--clu.size > 0)
- clu.dir++;
- else
- clu.dir = EXFAT_EOF_CLUSTER;
- } else {
- ret = exfat_get_next_cluster(sb, &clu.dir);
- }
+ ret = exfat_chain_advance(sb, &clu, 1);
if (ret || clu.dir == EXFAT_EOF_CLUSTER) {
/* just initialized hint_stat */
@@ -1176,20 +1149,12 @@ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir)
count++;
}
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- if (--clu.size > 0)
- clu.dir++;
- else
- clu.dir = EXFAT_EOF_CLUSTER;
- } else {
- if (exfat_get_next_cluster(sb, &(clu.dir)))
- return -EIO;
-
- if (unlikely(++clu_count > sbi->used_clusters)) {
- exfat_fs_error(sb, "FAT or bitmap is corrupted");
- return -EIO;
- }
+ if (exfat_chain_advance(sb, &clu, 1))
+ return -EIO;
+ if (unlikely(++clu_count > sbi->used_clusters)) {
+ exfat_fs_error(sb, "FAT or bitmap is corrupted");
+ return -EIO;
}
}
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index ef2a3488c1b3..e0d1c3bf5555 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -246,16 +246,8 @@ static int exfat_search_empty_slot(struct super_block *sb,
i += ret;
while (i >= dentries_per_clu) {
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- if (--clu.size > 0)
- clu.dir++;
- else
- clu.dir = EXFAT_EOF_CLUSTER;
- } else {
- if (exfat_get_next_cluster(sb, &clu.dir))
- return -EIO;
- }
-
+ if (exfat_chain_advance(sb, &clu, 1))
+ return -EIO;
i -= dentries_per_clu;
}
}
@@ -924,19 +916,12 @@ static int exfat_check_dir_empty(struct super_block *sb,
return -ENOTEMPTY;
}
- if (clu.flags == ALLOC_NO_FAT_CHAIN) {
- if (--clu.size > 0)
- clu.dir++;
- else
- clu.dir = EXFAT_EOF_CLUSTER;
- } else {
- if (exfat_get_next_cluster(sb, &(clu.dir)))
- return -EIO;
+ if (exfat_chain_advance(sb, &clu, 1))
+ return -EIO;
- /* break if the cluster chain includes a loop */
- if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
- break;
- }
+ /* break if the cluster chain includes a loop */
+ if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi)))
+ break;
}
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [syzbot ci] Re: exfat: unify FAT chain walking helpers
2026-03-31 9:11 [PATCH v1 0/6] exfat: unify FAT chain walking helpers Chi Zhiling
` (5 preceding siblings ...)
2026-03-31 9:11 ` [PATCH v1 6/6] exfat: use " Chi Zhiling
@ 2026-03-31 15:27 ` syzbot ci
2026-04-01 2:45 ` Chi Zhiling
6 siblings, 1 reply; 9+ messages in thread
From: syzbot ci @ 2026-03-31 15:27 UTC (permalink / raw)
To: chizhiling, chizhiling, linkinjeon, linux-fsdevel, linux-kernel,
sj1557.seo, yuezhang.mo
Cc: syzbot, syzkaller-bugs
syzbot ci has tested the following series
[v1] exfat: unify FAT chain walking helpers
https://lore.kernel.org/all/20260331091113.20882-1-chizhiling@163.com
* [PATCH v1 1/6] exfat: fix incorrect directory checksum after rename to shorter name
* [PATCH v1 2/6] exfat: introduce exfat_fat_walk helper
* [PATCH v1 3/6] exfat: use exfat_fat_walk helper to simplify fat entry walking
* [PATCH v1 4/6] exfat: remove NULL cache pointer case in exfat_ent_get
* [PATCH v1 5/6] exfat: introduce exfat_chain_advance helper
* [PATCH v1 6/6] exfat: use exfat_chain_advance helper
and found the following issue:
WARNING in exfat_find_empty_entry
Full report is available here:
https://ci.syzbot.org/series/d9d5a999-e11a-43e1-ac76-9c718e136f25
***
WARNING in exfat_find_empty_entry
tree: linux-next
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next
base: d1d75eaf01abceb3d5cb50253375b5f254b6be54
arch: amd64
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
config: https://ci.syzbot.org/builds/177ab8e9-7eef-44cc-8b1d-6e8e2b44adaf/config
C repro: https://ci.syzbot.org/findings/9b0e35b9-b5be-440e-9461-2f19c03cb16a/c_repro
syz repro: https://ci.syzbot.org/findings/9b0e35b9-b5be-440e-9461-2f19c03cb16a/syz_repro
exFAT-fs (loop0): start_clu is invalid cluster(0xffffffff)
exFAT-fs (loop0): valid_size(150994954) is greater than size(10)
------------[ cut here ]------------
chain->dir != EXFAT_EOF_CLUSTER
WARNING: fs/exfat/exfat_fs.h:575 at exfat_chain_advance fs/exfat/exfat_fs.h:575 [inline], CPU#0: syz.0.17/5981
WARNING: fs/exfat/exfat_fs.h:575 at exfat_search_empty_slot fs/exfat/namei.c:249 [inline], CPU#0: syz.0.17/5981
WARNING: fs/exfat/exfat_fs.h:575 at exfat_find_empty_entry+0x754/0x13b0 fs/exfat/namei.c:318, CPU#0: syz.0.17/5981
Modules linked in:
CPU: 0 UID: 0 PID: 5981 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:exfat_chain_advance fs/exfat/exfat_fs.h:575 [inline]
RIP: 0010:exfat_search_empty_slot fs/exfat/namei.c:249 [inline]
RIP: 0010:exfat_find_empty_entry+0x754/0x13b0 fs/exfat/namei.c:318
Code: 00 bf ff ff ff ff 44 89 e6 e8 18 56 1f ff 41 83 fc ff 75 10 e8 cd 51 1f ff 45 29 ee 0f 8d ad fe ff ff eb 12 e8 bd 51 1f ff 90 <0f> 0b 90 45 29 ee 0f 8d 99 fe ff ff e8 ab 51 1f ff 41 01 df 48 8b
RSP: 0018:ffffc9000499f340 EFLAGS: 00010293
RAX: ffffffff82a639c3 RBX: 0000000000000020 RCX: ffff88816d588000
RDX: 0000000000000000 RSI: 000000000000000b RDI: 00000000ffffffff
RBP: ffffc9000499f570 R08: ffff888119e14a5b R09: 1ffff110233c294b
R10: dffffc0000000000 R11: ffffed10233c294c R12: 000000000000000b
R13: 0000000000000080 R14: 0000000000000000 R15: 0000000000000060
FS: 000055557e214500(0000) GS:ffff88818de66000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000006200 CR3: 00000001bcf7c000 CR4: 00000000000006f0
Call Trace:
<TASK>
exfat_rename_file fs/exfat/namei.c:1025 [inline]
__exfat_rename fs/exfat/namei.c:1177 [inline]
exfat_rename+0xb49/0x1f90 fs/exfat/namei.c:1251
vfs_rename+0xa96/0xeb0 fs/namei.c:6026
filename_renameat2+0x539/0x9c0 fs/namei.c:6144
__do_sys_rename fs/namei.c:6188 [inline]
__se_sys_rename+0x55/0x2c0 fs/namei.c:6184
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f66f1b9c819
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffcad04e2e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000052
RAX: ffffffffffffffda RBX: 00007f66f1e15fa0 RCX: 00007f66f1b9c819
RDX: 0000000000000000 RSI: 0000200000000400 RDI: 0000200000006200
RBP: 00007f66f1c32c91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f66f1e15fac R14: 00007f66f1e15fa0 R15: 00007f66f1e15fa0
</TASK>
***
If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
Tested-by: syzbot@syzkaller.appspotmail.com
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
To test a patch for this bug, please reply with `#syz test`
(should be on a separate line).
The patch should be attached to the email.
Note: arguments like custom git repos and branches are not supported.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [syzbot ci] Re: exfat: unify FAT chain walking helpers
2026-03-31 15:27 ` [syzbot ci] Re: exfat: unify FAT chain walking helpers syzbot ci
@ 2026-04-01 2:45 ` Chi Zhiling
0 siblings, 0 replies; 9+ messages in thread
From: Chi Zhiling @ 2026-04-01 2:45 UTC (permalink / raw)
To: syzbot ci, chizhiling, linkinjeon, linux-fsdevel, linux-kernel,
sj1557.seo, yuezhang.mo
Cc: syzbot, syzkaller-bugs
On 3/31/26 11:27 PM, syzbot ci wrote:
> syzbot ci has tested the following series
>
> [v1] exfat: unify FAT chain walking helpers
> https://lore.kernel.org/all/20260331091113.20882-1-chizhiling@163.com
> * [PATCH v1 1/6] exfat: fix incorrect directory checksum after rename to shorter name
> * [PATCH v1 2/6] exfat: introduce exfat_fat_walk helper
> * [PATCH v1 3/6] exfat: use exfat_fat_walk helper to simplify fat entry walking
> * [PATCH v1 4/6] exfat: remove NULL cache pointer case in exfat_ent_get
> * [PATCH v1 5/6] exfat: introduce exfat_chain_advance helper
> * [PATCH v1 6/6] exfat: use exfat_chain_advance helper
>
> and found the following issue:
> WARNING in exfat_find_empty_entry
>
> Full report is available here:
> https://ci.syzbot.org/series/d9d5a999-e11a-43e1-ac76-9c718e136f25
>
> ***
>
> WARNING in exfat_find_empty_entry
>
> tree: linux-next
> URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/next/linux-next
> base: d1d75eaf01abceb3d5cb50253375b5f254b6be54
> arch: amd64
> compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
> config: https://ci.syzbot.org/builds/177ab8e9-7eef-44cc-8b1d-6e8e2b44adaf/config
> C repro: https://ci.syzbot.org/findings/9b0e35b9-b5be-440e-9461-2f19c03cb16a/c_repro
> syz repro: https://ci.syzbot.org/findings/9b0e35b9-b5be-440e-9461-2f19c03cb16a/syz_repro
>
> exFAT-fs (loop0): start_clu is invalid cluster(0xffffffff)
> exFAT-fs (loop0): valid_size(150994954) is greater than size(10)
> ------------[ cut here ]------------
> chain->dir != EXFAT_EOF_CLUSTER
> WARNING: fs/exfat/exfat_fs.h:575 at exfat_chain_advance fs/exfat/exfat_fs.h:575 [inline], CPU#0: syz.0.17/5981
> WARNING: fs/exfat/exfat_fs.h:575 at exfat_search_empty_slot fs/exfat/namei.c:249 [inline], CPU#0: syz.0.17/5981
> WARNING: fs/exfat/exfat_fs.h:575 at exfat_find_empty_entry+0x754/0x13b0 fs/exfat/namei.c:318, CPU#0: syz.0.17/5981
> Modules linked in:
> CPU: 0 UID: 0 PID: 5981 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
> RIP: 0010:exfat_chain_advance fs/exfat/exfat_fs.h:575 [inline]
> RIP: 0010:exfat_search_empty_slot fs/exfat/namei.c:249 [inline]
> RIP: 0010:exfat_find_empty_entry+0x754/0x13b0 fs/exfat/namei.c:318
> Code: 00 bf ff ff ff ff 44 89 e6 e8 18 56 1f ff 41 83 fc ff 75 10 e8 cd 51 1f ff 45 29 ee 0f 8d ad fe ff ff eb 12 e8 bd 51 1f ff 90 <0f> 0b 90 45 29 ee 0f 8d 99 fe ff ff e8 ab 51 1f ff 41 01 df 48 8b
> RSP: 0018:ffffc9000499f340 EFLAGS: 00010293
> RAX: ffffffff82a639c3 RBX: 0000000000000020 RCX: ffff88816d588000
> RDX: 0000000000000000 RSI: 000000000000000b RDI: 00000000ffffffff
> RBP: ffffc9000499f570 R08: ffff888119e14a5b R09: 1ffff110233c294b
> R10: dffffc0000000000 R11: ffffed10233c294c R12: 000000000000000b
> R13: 0000000000000080 R14: 0000000000000000 R15: 0000000000000060
> FS: 000055557e214500(0000) GS:ffff88818de66000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000200000006200 CR3: 00000001bcf7c000 CR4: 00000000000006f0
> Call Trace:
> <TASK>
> exfat_rename_file fs/exfat/namei.c:1025 [inline]
> __exfat_rename fs/exfat/namei.c:1177 [inline]
> exfat_rename+0xb49/0x1f90 fs/exfat/namei.c:1251
> vfs_rename+0xa96/0xeb0 fs/namei.c:6026
> filename_renameat2+0x539/0x9c0 fs/namei.c:6144
> __do_sys_rename fs/namei.c:6188 [inline]
> __se_sys_rename+0x55/0x2c0 fs/namei.c:6184
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> RIP: 0033:0x7f66f1b9c819
> Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
> RSP: 002b:00007ffcad04e2e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000052
> RAX: ffffffffffffffda RBX: 00007f66f1e15fa0 RCX: 00007f66f1b9c819
> RDX: 0000000000000000 RSI: 0000200000000400 RDI: 0000200000006200
> RBP: 00007f66f1c32c91 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
> R13: 00007f66f1e15fac R14: 00007f66f1e15fa0 R15: 00007f66f1e15fa0
> </TASK>
It looks like I should remove this WARN_ON_ONCE statement. This check is
not reasonable when accessing directories, and I will fix it in v2.
Thanks,
>
>
> ***
>
> If these findings have caused you to resend the series or submit a
> separate fix, please add the following tag to your commit message:
> Tested-by: syzbot@syzkaller.appspotmail.com
>
> ---
> This report is generated by a bot. It may contain errors.
> syzbot ci engineers can be reached at syzkaller@googlegroups.com.
>
> To test a patch for this bug, please reply with `#syz test`
> (should be on a separate line).
>
> The patch should be attached to the email.
> Note: arguments like custom git repos and branches are not supported.
^ permalink raw reply [flat|nested] 9+ messages in thread