[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251118082208.1034186-3-chizhiling@163.com>
Date: Tue, 18 Nov 2025 16:22:03 +0800
From: Chi Zhiling <chizhiling@....com>
To: linux-fsdevel@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: Alexander Viro <viro@...iv.linux.org.uk>,
Christian Brauner <brauner@...nel.org>,
Jan Kara <jack@...e.cz>,
Matthew Wilcox <willy@...radead.org>,
Namjae Jeon <linkinjeon@...nel.org>,
Sungjong Seo <sj1557.seo@...sung.com>,
Yuezhang Mo <yuezhang.mo@...y.com>,
Chi Zhiling <chizhiling@...inos.cn>
Subject: [RFC PATCH 2/7] exfat: support reuse buffer head for exfat_ent_get
From: Chi Zhiling <chizhiling@...inos.cn>
This patch is part 2 of cached buffer head for exfat_ent_get,
it introduces an argument for exfat_ent_get, and make sure this
routine releases buffer head refcount when any error return.
Signed-off-by: Chi Zhiling <chizhiling@...inos.cn>
---
fs/exfat/cache.c | 2 +-
fs/exfat/exfat_fs.h | 4 ++--
fs/exfat/fatent.c | 35 +++++++++++++++++++++++------------
3 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/fs/exfat/cache.c b/fs/exfat/cache.c
index d5ce0ae660ba..61af3fa05ab7 100644
--- a/fs/exfat/cache.c
+++ b/fs/exfat/cache.c
@@ -287,7 +287,7 @@ int exfat_get_cluster(struct inode *inode, unsigned int cluster,
return -EIO;
}
- if (exfat_ent_get(sb, *dclus, &content))
+ if (exfat_ent_get(sb, *dclus, &content, NULL))
return -EIO;
*last_dclus = *dclus;
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 329697c89d09..d52893276e9a 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -433,13 +433,13 @@ 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)
+#define exfat_get_next_cluster(sb, pclu) exfat_ent_get(sb, *(pclu), pclu, NULL)
int exfat_alloc_cluster(struct inode *inode, unsigned int num_alloc,
struct exfat_chain *p_chain, bool sync_bmap);
int exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain);
int exfat_ent_get(struct super_block *sb, unsigned int loc,
- unsigned int *content);
+ unsigned int *content, struct buffer_head **last);
int exfat_ent_set(struct super_block *sb, unsigned int loc,
unsigned int content);
int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c
index f9c5d3485865..a3a19c8d2e05 100644
--- a/fs/exfat/fatent.c
+++ b/fs/exfat/fatent.c
@@ -88,8 +88,11 @@ int exfat_ent_set(struct super_block *sb, unsigned int loc,
return 0;
}
+/*
+ * Caller must release the buffer_head if no error return.
+ */
int exfat_ent_get(struct super_block *sb, unsigned int loc,
- unsigned int *content)
+ unsigned int *content, struct buffer_head **last)
{
struct exfat_sb_info *sbi = EXFAT_SB(sb);
int err;
@@ -98,39 +101,47 @@ int exfat_ent_get(struct super_block *sb, unsigned int loc,
exfat_fs_error_ratelimit(sb,
"invalid access to FAT (entry 0x%08x)",
loc);
- return -EIO;
+ goto err;
}
- err = __exfat_ent_get(sb, loc, content, NULL);
- if (err) {
+ err = __exfat_ent_get(sb, loc, content, last);
+ if (unlikely(err)) {
exfat_fs_error_ratelimit(sb,
"failed to access to FAT (entry 0x%08x, err:%d)",
loc, err);
- return err;
+ goto err;
}
- if (*content == EXFAT_FREE_CLUSTER) {
+ if (unlikely(*content == EXFAT_FREE_CLUSTER)) {
exfat_fs_error_ratelimit(sb,
"invalid access to FAT free cluster (entry 0x%08x)",
loc);
- return -EIO;
+ goto err;
}
- if (*content == EXFAT_BAD_CLUSTER) {
+ if (unlikely(*content == EXFAT_BAD_CLUSTER)) {
exfat_fs_error_ratelimit(sb,
"invalid access to FAT bad cluster (entry 0x%08x)",
loc);
- return -EIO;
+ goto err;
}
if (*content != EXFAT_EOF_CLUSTER && !is_valid_cluster(sbi, *content)) {
exfat_fs_error_ratelimit(sb,
"invalid access to FAT (entry 0x%08x) bogus content (0x%08x)",
loc, *content);
- return -EIO;
+ goto err;
}
return 0;
+err:
+ if (last) {
+ brelse(*last);
+
+ /* Avoid double release */
+ *last = NULL;
+ }
+ return err;
}
int exfat_chain_cont_cluster(struct super_block *sb, unsigned int chain,
@@ -299,7 +310,7 @@ int exfat_find_last_cluster(struct super_block *sb, struct exfat_chain *p_chain,
do {
count++;
clu = next;
- if (exfat_ent_get(sb, clu, &next))
+ if (exfat_ent_get(sb, clu, &next, NULL))
return -EIO;
} while (next != EXFAT_EOF_CLUSTER && count <= p_chain->size);
@@ -490,7 +501,7 @@ int exfat_count_num_clusters(struct super_block *sb,
count = 0;
for (i = EXFAT_FIRST_CLUSTER; i < sbi->num_clusters; i++) {
count++;
- if (exfat_ent_get(sb, clu, &clu))
+ if (exfat_ent_get(sb, clu, &clu, NULL))
return -EIO;
if (clu == EXFAT_EOF_CLUSTER)
break;
--
2.43.0
Powered by blists - more mailing lists