Commit 943af1fd authored by Tetsuhiro Kohada's avatar Tetsuhiro Kohada Committed by Namjae Jeon

exfat: optimize dir-cache

Optimize directory access based on exfat_entry_set_cache.
 - Hold bh instead of copied d-entry.
 - Modify bh->data directly instead of the copied d-entry.
 - Write back the retained bh instead of rescanning the d-entry-set.
And
 - Remove unused cache related definitions.
Signed-off-by: default avatarTetsuhiro Kohada <kohada.tetsuhiro@dc.mitsubishielectric.co.jp>
Reviewed-by: default avatarSungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
parent ed0f84d3
...@@ -32,35 +32,30 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, ...@@ -32,35 +32,30 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb,
struct exfat_chain *p_dir, int entry, unsigned short *uniname) struct exfat_chain *p_dir, int entry, unsigned short *uniname)
{ {
int i; int i;
struct exfat_dentry *ep;
struct exfat_entry_set_cache *es; struct exfat_entry_set_cache *es;
es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES);
if (!es) if (!es)
return; return;
if (es->num_entries < 3)
goto free_es;
ep += 2;
/* /*
* First entry : file entry * First entry : file entry
* Second entry : stream-extension entry * Second entry : stream-extension entry
* Third entry : first file-name entry * Third entry : first file-name entry
* So, the index of first file-name dentry should start from 2. * So, the index of first file-name dentry should start from 2.
*/ */
for (i = 2; i < es->num_entries; i++, ep++) { for (i = 2; i < es->num_entries; i++) {
struct exfat_dentry *ep = exfat_get_dentry_cached(es, i);
/* end of name entry */ /* end of name entry */
if (exfat_get_entry_type(ep) != TYPE_EXTEND) if (exfat_get_entry_type(ep) != TYPE_EXTEND)
goto free_es; break;
exfat_extract_uni_name(ep, uniname); exfat_extract_uni_name(ep, uniname);
uniname += EXFAT_FILE_NAME_LEN; uniname += EXFAT_FILE_NAME_LEN;
} }
free_es: exfat_free_dentry_set(es, false);
kfree(es);
} }
/* read a directory entry from the opened directory */ /* read a directory entry from the opened directory */
...@@ -590,62 +585,33 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, ...@@ -590,62 +585,33 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
return 0; return 0;
} }
int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es)
struct exfat_entry_set_cache *es, int sync)
{ {
struct exfat_sb_info *sbi = EXFAT_SB(sb); int chksum_type = CS_DIR_ENTRY, i;
struct buffer_head *bh;
sector_t sec = es->sector;
unsigned int off = es->offset;
int chksum_type = CS_DIR_ENTRY, i, num_entries = es->num_entries;
unsigned int buf_off = (off - es->offset);
unsigned int remaining_byte_in_sector, copy_entries, clu;
unsigned short chksum = 0; unsigned short chksum = 0;
struct exfat_dentry *ep;
for (i = 0; i < num_entries; i++) { for (i = 0; i < es->num_entries; i++) {
chksum = exfat_calc_chksum_2byte(&es->entries[i], DENTRY_SIZE, ep = exfat_get_dentry_cached(es, i);
chksum, chksum_type); chksum = exfat_calc_chksum_2byte(ep, DENTRY_SIZE, chksum,
chksum_type);
chksum_type = CS_DEFAULT; chksum_type = CS_DEFAULT;
} }
ep = exfat_get_dentry_cached(es, 0);
ep->dentry.file.checksum = cpu_to_le16(chksum);
es->modified = true;
}
es->entries[0].dentry.file.checksum = cpu_to_le16(chksum); void exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
{
while (num_entries) { int i;
/* write per sector base */
remaining_byte_in_sector = (1 << sb->s_blocksize_bits) - off;
copy_entries = min_t(int,
EXFAT_B_TO_DEN(remaining_byte_in_sector),
num_entries);
bh = sb_bread(sb, sec);
if (!bh)
goto err_out;
memcpy(bh->b_data + off,
(unsigned char *)&es->entries[0] + buf_off,
EXFAT_DEN_TO_B(copy_entries));
exfat_update_bh(sb, bh, sync);
brelse(bh);
num_entries -= copy_entries;
if (num_entries) { for (i = 0; i < es->num_bh; i++) {
/* get next sector */ if (es->modified)
if (exfat_is_last_sector_in_cluster(sbi, sec)) { exfat_update_bh(es->sb, es->bh[i], sync);
clu = exfat_sector_to_cluster(sbi, sec); brelse(es->bh[i]);
if (es->alloc_flag == ALLOC_NO_FAT_CHAIN)
clu++;
else if (exfat_get_next_cluster(sb, &clu))
goto err_out;
sec = exfat_cluster_to_sector(sbi, clu);
} else {
sec++;
}
off = 0;
buf_off += EXFAT_DEN_TO_B(copy_entries);
} }
} kfree(es);
return 0;
err_out:
return -EIO;
} }
static int exfat_walk_fat_chain(struct super_block *sb, static int exfat_walk_fat_chain(struct super_block *sb,
...@@ -820,34 +786,40 @@ static bool exfat_validate_entry(unsigned int type, ...@@ -820,34 +786,40 @@ static bool exfat_validate_entry(unsigned int type,
} }
} }
struct exfat_dentry *exfat_get_dentry_cached(
struct exfat_entry_set_cache *es, int num)
{
int off = es->start_off + num * DENTRY_SIZE;
struct buffer_head *bh = es->bh[EXFAT_B_TO_BLK(off, es->sb)];
char *p = bh->b_data + EXFAT_BLK_OFFSET(off, es->sb);
return (struct exfat_dentry *)p;
}
/* /*
* Returns a set of dentries for a file or dir. * Returns a set of dentries for a file or dir.
* *
* Note that this is a copy (dump) of dentries so that user should * Note It provides a direct pointer to bh->data via exfat_get_dentry_cached().
* call write_entry_set() to apply changes made in this entry set * User should call exfat_get_dentry_set() after setting 'modified' to apply
* to the real device. * changes made in this entry set to the real device.
* *
* in: * in:
* sb+p_dir+entry: indicates a file/dir * sb+p_dir+entry: indicates a file/dir
* type: specifies how many dentries should be included. * type: specifies how many dentries should be included.
* out:
* file_ep: will point the first dentry(= file dentry) on success
* return: * return:
* pointer of entry set on success, * pointer of entry set on success,
* NULL on failure. * NULL on failure.
*/ */
struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
struct exfat_chain *p_dir, int entry, unsigned int type, struct exfat_chain *p_dir, int entry, unsigned int type)
struct exfat_dentry **file_ep)
{ {
int ret; int ret, i, num_bh;
unsigned int off, byte_offset, clu = 0; unsigned int off, byte_offset, clu = 0;
unsigned int entry_type;
sector_t sec; sector_t sec;
struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_entry_set_cache *es; struct exfat_entry_set_cache *es;
struct exfat_dentry *ep, *pos; struct exfat_dentry *ep;
unsigned char num_entries; int num_entries;
enum exfat_validate_dentry_mode mode = ES_MODE_STARTED; enum exfat_validate_dentry_mode mode = ES_MODE_STARTED;
struct buffer_head *bh; struct buffer_head *bh;
...@@ -861,11 +833,18 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, ...@@ -861,11 +833,18 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
if (ret) if (ret)
return NULL; return NULL;
es = kzalloc(sizeof(*es), GFP_KERNEL);
if (!es)
return NULL;
es->sb = sb;
es->modified = false;
/* byte offset in cluster */ /* byte offset in cluster */
byte_offset = EXFAT_CLU_OFFSET(byte_offset, sbi); byte_offset = EXFAT_CLU_OFFSET(byte_offset, sbi);
/* 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;
/* sector offset in cluster */ /* sector offset in cluster */
sec = EXFAT_B_TO_BLK(byte_offset, sb); sec = EXFAT_B_TO_BLK(byte_offset, sb);
...@@ -873,42 +852,22 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, ...@@ -873,42 +852,22 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
bh = sb_bread(sb, sec); bh = sb_bread(sb, sec);
if (!bh) if (!bh)
return NULL; goto free_es;
es->bh[es->num_bh++] = bh;
ep = (struct exfat_dentry *)(bh->b_data + off);
entry_type = exfat_get_entry_type(ep);
if (entry_type != TYPE_FILE && entry_type != TYPE_DIR) ep = exfat_get_dentry_cached(es, 0);
goto release_bh; if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
goto free_es;
num_entries = type == ES_ALL_ENTRIES ? num_entries = type == ES_ALL_ENTRIES ?
ep->dentry.file.num_ext + 1 : type; ep->dentry.file.num_ext + 1 : type;
es = kmalloc(struct_size(es, entries, num_entries), GFP_KERNEL);
if (!es)
goto release_bh;
es->num_entries = num_entries; es->num_entries = num_entries;
es->sector = sec;
es->offset = off;
es->alloc_flag = p_dir->flags;
pos = &es->entries[0]; num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb);
for (i = 1; i < num_bh; i++) {
while (num_entries) {
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
goto free_es;
/* copy dentry */
memcpy(pos, ep, sizeof(struct exfat_dentry));
if (--num_entries == 0)
break;
if (((off + DENTRY_SIZE) & (sb->s_blocksize - 1)) <
(off & (sb->s_blocksize - 1))) {
/* 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)) {
if (es->alloc_flag == ALLOC_NO_FAT_CHAIN) if (p_dir->flags == ALLOC_NO_FAT_CHAIN)
clu++; clu++;
else if (exfat_get_next_cluster(sb, &clu)) else if (exfat_get_next_cluster(sb, &clu))
goto free_es; goto free_es;
...@@ -917,28 +876,22 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, ...@@ -917,28 +876,22 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
sec++; sec++;
} }
brelse(bh);
bh = sb_bread(sb, sec); bh = sb_bread(sb, sec);
if (!bh) if (!bh)
goto free_es; goto free_es;
off = 0; es->bh[es->num_bh++] = bh;
ep = (struct exfat_dentry *)bh->b_data;
} else {
ep++;
off += DENTRY_SIZE;
}
pos++;
} }
if (file_ep) /* validiate cached dentries */
*file_ep = &es->entries[0]; for (i = 1; i < num_entries; i++) {
brelse(bh); ep = exfat_get_dentry_cached(es, i);
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
goto free_es;
}
return es; return es;
free_es: free_es:
kfree(es); exfat_free_dentry_set(es, false);
release_bh:
brelse(bh);
return NULL; return NULL;
} }
......
...@@ -71,10 +71,8 @@ enum { ...@@ -71,10 +71,8 @@ enum {
#define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */ #define MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */
#define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE) #define MAX_VFSNAME_BUF_SIZE ((MAX_NAME_LENGTH + 1) * MAX_CHARSET_SIZE)
#define FAT_CACHE_SIZE 128 /* Enough size to hold 256 dentry (even 512 Byte sector) */
#define FAT_CACHE_HASH_SIZE 64 #define DIR_CACHE_SIZE (256*sizeof(struct exfat_dentry)/512+1)
#define BUF_CACHE_SIZE 256
#define BUF_CACHE_HASH_SIZE 64
#define EXFAT_HINT_NONE -1 #define EXFAT_HINT_NONE -1
#define EXFAT_MIN_SUBDIR 2 #define EXFAT_MIN_SUBDIR 2
...@@ -170,14 +168,12 @@ struct exfat_hint { ...@@ -170,14 +168,12 @@ struct exfat_hint {
}; };
struct exfat_entry_set_cache { struct exfat_entry_set_cache {
/* sector number that contains file_entry */ struct super_block *sb;
sector_t sector; bool modified;
/* byte offset in the sector */ unsigned int start_off;
unsigned int offset; int num_bh;
/* flag in stream entry. 01 for cluster chain, 03 for contig. */ struct buffer_head *bh[DIR_CACHE_SIZE];
int alloc_flag;
unsigned int num_entries; unsigned int num_entries;
struct exfat_dentry entries[];
}; };
struct exfat_dir_entry { struct exfat_dir_entry {
...@@ -451,8 +447,7 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir, ...@@ -451,8 +447,7 @@ int exfat_remove_entries(struct inode *inode, struct exfat_chain *p_dir,
int entry, int order, int num_entries); int entry, int order, int num_entries);
int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir, int exfat_update_dir_chksum(struct inode *inode, struct exfat_chain *p_dir,
int entry); int entry);
int exfat_update_dir_chksum_with_entry_set(struct super_block *sb, void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es);
struct exfat_entry_set_cache *es, int sync);
int exfat_calc_num_entries(struct exfat_uni_name *p_uniname); int exfat_calc_num_entries(struct exfat_uni_name *p_uniname);
int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname,
...@@ -463,9 +458,11 @@ int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir, ...@@ -463,9 +458,11 @@ int exfat_find_location(struct super_block *sb, struct exfat_chain *p_dir,
struct exfat_dentry *exfat_get_dentry(struct super_block *sb, struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
struct exfat_chain *p_dir, int entry, struct buffer_head **bh, struct exfat_chain *p_dir, int entry, struct buffer_head **bh,
sector_t *sector); sector_t *sector);
struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
int num);
struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb, struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
struct exfat_chain *p_dir, int entry, unsigned int type, struct exfat_chain *p_dir, int entry, unsigned int type);
struct exfat_dentry **file_ep); void exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync);
int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir); int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir);
/* inode.c */ /* inode.c */
......
...@@ -96,11 +96,9 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) ...@@ -96,11 +96,9 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
unsigned int num_clusters_new, num_clusters_phys; unsigned int num_clusters_new, num_clusters_phys;
unsigned int last_clu = EXFAT_FREE_CLUSTER; unsigned int last_clu = EXFAT_FREE_CLUSTER;
struct exfat_chain clu; struct exfat_chain clu;
struct exfat_dentry *ep, *ep2;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_inode_info *ei = EXFAT_I(inode); struct exfat_inode_info *ei = EXFAT_I(inode);
struct exfat_entry_set_cache *es = NULL;
int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0; int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0;
/* check if the given file ID is opened */ /* check if the given file ID is opened */
...@@ -153,12 +151,15 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) ...@@ -153,12 +151,15 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
/* update the directory entry */ /* update the directory entry */
if (!evict) { if (!evict) {
struct timespec64 ts; struct timespec64 ts;
struct exfat_dentry *ep, *ep2;
struct exfat_entry_set_cache *es;
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
ES_ALL_ENTRIES, &ep); ES_ALL_ENTRIES);
if (!es) if (!es)
return -EIO; return -EIO;
ep2 = ep + 1; ep = exfat_get_dentry_cached(es, 0);
ep2 = exfat_get_dentry_cached(es, 1);
ts = current_time(inode); ts = current_time(inode);
exfat_set_entry_time(sbi, &ts, exfat_set_entry_time(sbi, &ts,
...@@ -185,10 +186,8 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) ...@@ -185,10 +186,8 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER; ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
} }
if (exfat_update_dir_chksum_with_entry_set(sb, es, exfat_update_dir_chksum_with_entry_set(es);
inode_needs_sync(inode))) exfat_free_dentry_set(es, inode_needs_sync(inode));
return -EIO;
kfree(es);
} }
/* cut off from the FAT chain */ /* cut off from the FAT chain */
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
static int __exfat_write_inode(struct inode *inode, int sync) static int __exfat_write_inode(struct inode *inode, int sync)
{ {
int ret = -EIO;
unsigned long long on_disk_size; unsigned long long on_disk_size;
struct exfat_dentry *ep, *ep2; struct exfat_dentry *ep, *ep2;
struct exfat_entry_set_cache *es = NULL; struct exfat_entry_set_cache *es = NULL;
...@@ -43,11 +42,11 @@ static int __exfat_write_inode(struct inode *inode, int sync) ...@@ -43,11 +42,11 @@ static int __exfat_write_inode(struct inode *inode, int sync)
exfat_set_vol_flags(sb, VOL_DIRTY); exfat_set_vol_flags(sb, VOL_DIRTY);
/* get the directory entry of given file or directory */ /* get the directory entry of given file or directory */
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES, es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, ES_ALL_ENTRIES);
&ep);
if (!es) if (!es)
return -EIO; return -EIO;
ep2 = ep + 1; ep = exfat_get_dentry_cached(es, 0);
ep2 = exfat_get_dentry_cached(es, 1);
ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode)); ep->dentry.file.attr = cpu_to_le16(exfat_make_attr(inode));
...@@ -77,9 +76,9 @@ static int __exfat_write_inode(struct inode *inode, int sync) ...@@ -77,9 +76,9 @@ static int __exfat_write_inode(struct inode *inode, int sync)
ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size); ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size);
ep2->dentry.stream.size = ep2->dentry.stream.valid_size; ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
ret = exfat_update_dir_chksum_with_entry_set(sb, es, sync); exfat_update_dir_chksum_with_entry_set(es);
kfree(es); exfat_free_dentry_set(es, sync);
return ret; return 0;
} }
int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) int exfat_write_inode(struct inode *inode, struct writeback_control *wbc)
...@@ -110,8 +109,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, ...@@ -110,8 +109,6 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
int ret, modified = false; int ret, modified = false;
unsigned int last_clu; unsigned int last_clu;
struct exfat_chain new_clu; struct exfat_chain new_clu;
struct exfat_dentry *ep;
struct exfat_entry_set_cache *es = NULL;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_inode_info *ei = EXFAT_I(inode); struct exfat_inode_info *ei = EXFAT_I(inode);
...@@ -222,34 +219,28 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset, ...@@ -222,34 +219,28 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
num_clusters += num_to_be_allocated; num_clusters += num_to_be_allocated;
*clu = new_clu.dir; *clu = new_clu.dir;
if (ei->dir.dir != DIR_DELETED) { if (ei->dir.dir != DIR_DELETED && modified) {
struct exfat_dentry *ep;
struct exfat_entry_set_cache *es;
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry, es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
ES_ALL_ENTRIES, &ep); ES_ALL_ENTRIES);
if (!es) if (!es)
return -EIO; return -EIO;
/* get stream entry */ /* get stream entry */
ep++; ep = exfat_get_dentry_cached(es, 1);
/* update directory entry */ /* update directory entry */
if (modified) {
if (ep->dentry.stream.flags != ei->flags)
ep->dentry.stream.flags = ei->flags; ep->dentry.stream.flags = ei->flags;
if (le32_to_cpu(ep->dentry.stream.start_clu) !=
ei->start_clu)
ep->dentry.stream.start_clu = ep->dentry.stream.start_clu =
cpu_to_le32(ei->start_clu); cpu_to_le32(ei->start_clu);
ep->dentry.stream.valid_size = ep->dentry.stream.valid_size =
cpu_to_le64(i_size_read(inode)); cpu_to_le64(i_size_read(inode));
ep->dentry.stream.size = ep->dentry.stream.size =
ep->dentry.stream.valid_size; ep->dentry.stream.valid_size;
}
if (exfat_update_dir_chksum_with_entry_set(sb, es, exfat_update_dir_chksum_with_entry_set(es);
inode_needs_sync(inode))) exfat_free_dentry_set(es, inode_needs_sync(inode));
return -EIO;
kfree(es);
} /* end of if != DIR_DELETED */ } /* end of if != DIR_DELETED */
......
...@@ -600,8 +600,6 @@ static int exfat_find(struct inode *dir, struct qstr *qname, ...@@ -600,8 +600,6 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
int ret, dentry, num_entries, count; int ret, dentry, num_entries, count;
struct exfat_chain cdir; struct exfat_chain cdir;
struct exfat_uni_name uni_name; struct exfat_uni_name uni_name;
struct exfat_dentry *ep, *ep2;
struct exfat_entry_set_cache *es = NULL;
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_inode_info *ei = EXFAT_I(dir); struct exfat_inode_info *ei = EXFAT_I(dir);
...@@ -660,10 +658,14 @@ static int exfat_find(struct inode *dir, struct qstr *qname, ...@@ -660,10 +658,14 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
info->num_subdirs = count; info->num_subdirs = count;
} else { } else {
es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES, &ep); struct exfat_dentry *ep, *ep2;
struct exfat_entry_set_cache *es;
es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES);
if (!es) if (!es)
return -EIO; return -EIO;
ep2 = ep + 1; ep = exfat_get_dentry_cached(es, 0);
ep2 = exfat_get_dentry_cached(es, 1);
info->type = exfat_get_entry_type(ep); info->type = exfat_get_entry_type(ep);
info->attr = le16_to_cpu(ep->dentry.file.attr); info->attr = le16_to_cpu(ep->dentry.file.attr);
...@@ -681,7 +683,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, ...@@ -681,7 +683,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
exfat_fs_error(sb, exfat_fs_error(sb,
"non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)",
i_size_read(dir), ei->dir.dir, ei->entry); i_size_read(dir), ei->dir.dir, ei->entry);
kfree(es); exfat_free_dentry_set(es, false);
return -EIO; return -EIO;
} }
...@@ -700,7 +702,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, ...@@ -700,7 +702,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname,
ep->dentry.file.access_time, ep->dentry.file.access_time,
ep->dentry.file.access_date, ep->dentry.file.access_date,
0); 0);
kfree(es); exfat_free_dentry_set(es, false);
if (info->type == TYPE_DIR) { if (info->type == TYPE_DIR) {
exfat_chain_set(&cdir, info->start_clu, exfat_chain_set(&cdir, info->start_clu,
......
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