Commit a3ff29a9 authored by Yuezhang Mo's avatar Yuezhang Mo Committed by Namjae Jeon

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: default avatarYuezhang Mo <Yuezhang.Mo@sony.com>
Reviewed-by: default avatarAndy Wu <Andy.Wu@sony.com>
Reviewed-by: default avatarAoyama Wataru <wataru.aoyama@sony.com>
Reviewed-by: default avatarSungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
parent f83d8a3b
...@@ -615,6 +615,10 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync) ...@@ -615,6 +615,10 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
bforget(es->bh[i]); bforget(es->bh[i]);
else else
brelse(es->bh[i]); brelse(es->bh[i]);
if (IS_DYNAMIC_ES(es))
kfree(es->bh);
kfree(es); kfree(es);
return err; return err;
} }
...@@ -847,6 +851,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, ...@@ -847,6 +851,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
/* byte offset in sector */ /* byte offset in sector */
off = EXFAT_BLK_OFFSET(byte_offset, sb); off = EXFAT_BLK_OFFSET(byte_offset, sb);
es->start_off = off; es->start_off = off;
es->bh = es->__bh;
/* sector offset in cluster */ /* sector offset in cluster */
sec = EXFAT_B_TO_BLK(byte_offset, sb); 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, ...@@ -866,6 +871,16 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
es->num_entries = num_entries; es->num_entries = num_entries;
num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb); 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++) { for (i = 1; i < num_bh; i++) {
/* get the next sector */ /* get the next sector */
if (exfat_is_last_sector_in_cluster(sbi, sec)) { if (exfat_is_last_sector_in_cluster(sbi, sec)) {
......
...@@ -185,11 +185,14 @@ struct exfat_entry_set_cache { ...@@ -185,11 +185,14 @@ struct exfat_entry_set_cache {
struct super_block *sb; struct super_block *sb;
unsigned int start_off; unsigned int start_off;
int num_bh; 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; unsigned int num_entries;
bool modified; bool modified;
}; };
#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
struct exfat_dir_entry { struct exfat_dir_entry {
struct exfat_chain dir; struct exfat_chain dir;
int entry; int entry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment