Commit 7b6bab23 authored by Yuezhang Mo's avatar Yuezhang Mo Committed by Namjae Jeon

exfat: add __exfat_get_dentry_set() helper

Since exfat_get_dentry_set() invokes the validate functions of
exfat_validate_entry(), it only supports getting a directory
entry set of an existing file, doesn't support getting an empty
entry set.

To remove the limitation, add this helper.
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 855684c7
...@@ -775,7 +775,6 @@ struct exfat_dentry *exfat_get_dentry(struct super_block *sb, ...@@ -775,7 +775,6 @@ struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
} }
enum exfat_validate_dentry_mode { enum exfat_validate_dentry_mode {
ES_MODE_STARTED,
ES_MODE_GET_FILE_ENTRY, ES_MODE_GET_FILE_ENTRY,
ES_MODE_GET_STRM_ENTRY, ES_MODE_GET_STRM_ENTRY,
ES_MODE_GET_NAME_ENTRY, ES_MODE_GET_NAME_ENTRY,
...@@ -790,11 +789,6 @@ static bool exfat_validate_entry(unsigned int type, ...@@ -790,11 +789,6 @@ static bool exfat_validate_entry(unsigned int type,
return false; return false;
switch (*mode) { switch (*mode) {
case ES_MODE_STARTED:
if (type != TYPE_FILE && type != TYPE_DIR)
return false;
*mode = ES_MODE_GET_FILE_ENTRY;
break;
case ES_MODE_GET_FILE_ENTRY: case ES_MODE_GET_FILE_ENTRY:
if (type != TYPE_STREAM) if (type != TYPE_STREAM)
return false; return false;
...@@ -834,7 +828,7 @@ struct exfat_dentry *exfat_get_dentry_cached( ...@@ -834,7 +828,7 @@ struct exfat_dentry *exfat_get_dentry_cached(
} }
/* /*
* Returns a set of dentries for a file or dir. * Returns a set of dentries.
* *
* Note It provides a direct pointer to bh->data via exfat_get_dentry_cached(). * Note It provides a direct pointer to bh->data via exfat_get_dentry_cached().
* User should call exfat_get_dentry_set() after setting 'modified' to apply * User should call exfat_get_dentry_set() after setting 'modified' to apply
...@@ -842,22 +836,24 @@ struct exfat_dentry *exfat_get_dentry_cached( ...@@ -842,22 +836,24 @@ struct exfat_dentry *exfat_get_dentry_cached(
* *
* 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. * num_entries: specifies how many dentries should be included.
* It will be set to es->num_entries if it is not 0.
* If num_entries is 0, es->num_entries will be obtained
* from the first dentry.
* out:
* es: pointer of entry set on success.
* return: * return:
* pointer of entry set on success, * 0 on success
* NULL on failure. * -error code on failure
*/ */
int exfat_get_dentry_set(struct exfat_entry_set_cache *es, static int __exfat_get_dentry_set(struct exfat_entry_set_cache *es,
struct super_block *sb, struct exfat_chain *p_dir, int entry, struct super_block *sb, struct exfat_chain *p_dir, int entry,
unsigned int type) unsigned int num_entries)
{ {
int ret, i, num_bh; int ret, i, num_bh;
unsigned int off; unsigned int off;
sector_t sec; sector_t sec;
struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_dentry *ep;
int num_entries;
enum exfat_validate_dentry_mode mode = ES_MODE_STARTED;
struct buffer_head *bh; struct buffer_head *bh;
if (p_dir->dir == DIR_DELETED) { if (p_dir->dir == DIR_DELETED) {
...@@ -880,12 +876,18 @@ int exfat_get_dentry_set(struct exfat_entry_set_cache *es, ...@@ -880,12 +876,18 @@ int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
return -EIO; return -EIO;
es->bh[es->num_bh++] = bh; es->bh[es->num_bh++] = bh;
ep = exfat_get_dentry_cached(es, ES_IDX_FILE); if (num_entries == ES_ALL_ENTRIES) {
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) struct exfat_dentry *ep;
goto put_es;
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
if (ep->type != EXFAT_FILE) {
brelse(bh);
return -EIO;
}
num_entries = ep->dentry.file.num_ext + 1;
}
num_entries = type == ES_ALL_ENTRIES ?
ep->dentry.file.num_ext + 1 : type;
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);
...@@ -918,8 +920,27 @@ int exfat_get_dentry_set(struct exfat_entry_set_cache *es, ...@@ -918,8 +920,27 @@ int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
es->bh[es->num_bh++] = bh; es->bh[es->num_bh++] = bh;
} }
return 0;
put_es:
exfat_put_dentry_set(es, false);
return -EIO;
}
int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
struct super_block *sb, struct exfat_chain *p_dir,
int entry, unsigned int num_entries)
{
int ret, i;
struct exfat_dentry *ep;
enum exfat_validate_dentry_mode mode = ES_MODE_GET_FILE_ENTRY;
ret = __exfat_get_dentry_set(es, sb, p_dir, entry, num_entries);
if (ret < 0)
return ret;
/* validate cached dentries */ /* validate cached dentries */
for (i = ES_IDX_STREAM; i < num_entries; i++) { for (i = ES_IDX_STREAM; i < es->num_entries; i++) {
ep = exfat_get_dentry_cached(es, i); ep = exfat_get_dentry_cached(es, i);
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode)) if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
goto put_es; goto put_es;
......
...@@ -501,7 +501,7 @@ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es, ...@@ -501,7 +501,7 @@ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
int num); int num);
int exfat_get_dentry_set(struct exfat_entry_set_cache *es, int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
struct super_block *sb, struct exfat_chain *p_dir, int entry, struct super_block *sb, struct exfat_chain *p_dir, int entry,
unsigned int type); unsigned int num_entries);
int exfat_put_dentry_set(struct exfat_entry_set_cache *es, int sync); int exfat_put_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);
......
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