[<prev] [next>] [day] [month] [year] [list]
Message-ID: <PUZPR04MB63163CD638A35F7835184D7D81069@PUZPR04MB6316.apcprd04.prod.outlook.com>
Date: Thu, 17 Nov 2022 05:46:56 +0000
From: "Yuezhang.Mo@...y.com" <Yuezhang.Mo@...y.com>
To: Namjae Jeon <linkinjeon@...nel.org>,
Sungjong Seo <sj1557.seo@...sung.com>
CC: linux-kernel <linux-kernel@...r.kernel.org>,
linux-fsdevel <linux-fsdevel@...r.kernel.org>,
"Andy.Wu@...y.com" <Andy.Wu@...y.com>,
"Wataru.Aoyama@...y.com" <Wataru.Aoyama@...y.com>
Subject: [PATCH v1 2/5] exfat: support dynamic allocate bh for
exfat_entry_set_cache
In special cases, a file or a directory may occupied more than 19
directory entries, pre-allocating 3 bh is not enough. Such as
- Support vendor secondary directory entry in the future.
- Since file directory entry is damaged, the SecondaryCount
field is bigger than 18.
So this commit supports dynamic allocation of bh.
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@...y.com>
Reviewed-by: Andy Wu <Andy.Wu@...y.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@...y.com>
---
fs/exfat/dir.c | 15 +++++++++++++++
fs/exfat/exfat_fs.h | 5 ++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index 30d0ac43b66c..03e9c9e3966e 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -615,6 +615,10 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
bforget(es->bh[i]);
else
brelse(es->bh[i]);
+
+ if (IS_DYNAMIC_ES(es))
+ kfree(es->bh);
+
kfree(es);
return err;
}
@@ -847,6 +851,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
/* byte offset in sector */
off = EXFAT_BLK_OFFSET(byte_offset, sb);
es->start_off = off;
+ es->bh = es->__bh;
/* sector offset in cluster */
sec = EXFAT_B_TO_BLK(byte_offset, sb);
@@ -866,6 +871,16 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
es->num_entries = num_entries;
num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb);
+ if (num_bh > ARRAY_SIZE(es->__bh)) {
+ es->bh = kmalloc_array(num_bh, sizeof(*es->bh), GFP_KERNEL);
+ if (!es->bh) {
+ brelse(bh);
+ kfree(es);
+ return NULL;
+ }
+ es->bh[0] = bh;
+ }
+
for (i = 1; i < num_bh; i++) {
/* get the next sector */
if (exfat_is_last_sector_in_cluster(sbi, sec)) {
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 7d2493cda5d8..33a3d544365a 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -184,11 +184,14 @@ struct exfat_entry_set_cache {
struct super_block *sb;
unsigned int start_off;
int num_bh;
- struct buffer_head *bh[DIR_CACHE_SIZE];
+ struct buffer_head *__bh[DIR_CACHE_SIZE];
+ struct buffer_head **bh;
unsigned int num_entries;
bool modified;
};
+#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
+
struct exfat_dir_entry {
struct exfat_chain dir;
int entry;
--
2.25.1
Powered by blists - more mailing lists