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: 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:
Yuezhang Mo 2023-12-08 19:17:02 +08:00 committed by Namjae Jeon
parent 855684c7d9
commit 7b6bab2359
2 changed files with 43 additions and 22 deletions

View File

@ -775,7 +775,6 @@ struct exfat_dentry *exfat_get_dentry(struct super_block *sb,
}
enum exfat_validate_dentry_mode {
ES_MODE_STARTED,
ES_MODE_GET_FILE_ENTRY,
ES_MODE_GET_STRM_ENTRY,
ES_MODE_GET_NAME_ENTRY,
@ -790,11 +789,6 @@ static bool exfat_validate_entry(unsigned int type,
return false;
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:
if (type != TYPE_STREAM)
return false;
@ -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().
* User should call exfat_get_dentry_set() after setting 'modified' to apply
@ -842,22 +836,24 @@ struct exfat_dentry *exfat_get_dentry_cached(
*
* in:
* 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:
* pointer of entry set on success,
* NULL on failure.
* 0 on success
* -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,
unsigned int type)
unsigned int num_entries)
{
int ret, i, num_bh;
unsigned int off;
sector_t sec;
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;
if (p_dir->dir == DIR_DELETED) {
@ -880,12 +876,18 @@ int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
return -EIO;
es->bh[es->num_bh++] = bh;
ep = exfat_get_dentry_cached(es, ES_IDX_FILE);
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
goto put_es;
if (num_entries == ES_ALL_ENTRIES) {
struct exfat_dentry *ep;
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;
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,
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 */
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);
if (!exfat_validate_entry(exfat_get_entry_type(ep), &mode))
goto put_es;

View File

@ -501,7 +501,7 @@ struct exfat_dentry *exfat_get_dentry_cached(struct exfat_entry_set_cache *es,
int num);
int exfat_get_dentry_set(struct exfat_entry_set_cache *es,
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_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir);