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@sony.com> Reviewed-by: Andy Wu <Andy.Wu@sony.com> Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com> Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Родитель
f83d8a3b53
Коммит
a3ff29a95f
|
@ -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,
|
||||||
/* 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,
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче