exfat: reuse __exfat_write_inode() to update directory entry

__exfat_write_inode() is used to update file and stream directory
entries, except for file->start_clu and stream->flags.

This commit moves update file->start_clu and stream->flags to
__exfat_write_inode() and reuse __exfat_write_inode() to update
directory entries.

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: Daniel Palmer <daniel.palmer@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 2022-06-29 09:51:40 +08:00 committed by Namjae Jeon
parent 3d7cb6b04c
commit 23e6e1c9b3
4 changed files with 19 additions and 90 deletions

View File

@ -483,6 +483,7 @@ struct inode *exfat_build_inode(struct super_block *sb,
void exfat_hash_inode(struct inode *inode, loff_t i_pos); void exfat_hash_inode(struct inode *inode, loff_t i_pos);
void exfat_unhash_inode(struct inode *inode); void exfat_unhash_inode(struct inode *inode);
struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); struct inode *exfat_iget(struct super_block *sb, loff_t i_pos);
int __exfat_write_inode(struct inode *inode, int sync);
int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); int exfat_write_inode(struct inode *inode, struct writeback_control *wbc);
void exfat_evict_inode(struct inode *inode); void exfat_evict_inode(struct inode *inode);
int exfat_block_truncate_page(struct inode *inode, loff_t from); int exfat_block_truncate_page(struct inode *inode, loff_t from);

View File

@ -101,7 +101,6 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
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);
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 */
if (ei->type != TYPE_FILE && ei->type != TYPE_DIR) if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
@ -150,49 +149,9 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
ei->attr |= ATTR_ARCHIVE; ei->attr |= ATTR_ARCHIVE;
/* update the directory entry */ /* update the directory entry */
if (!evict) { inode->i_mtime = current_time(inode);
struct timespec64 ts; if (__exfat_write_inode(inode, inode_needs_sync(inode)))
struct exfat_dentry *ep, *ep2; return -EIO;
struct exfat_entry_set_cache *es;
int err;
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
ES_ALL_ENTRIES);
if (!es)
return -EIO;
ep = exfat_get_dentry_cached(es, 0);
ep2 = exfat_get_dentry_cached(es, 1);
ts = current_time(inode);
exfat_set_entry_time(sbi, &ts,
&ep->dentry.file.modify_tz,
&ep->dentry.file.modify_time,
&ep->dentry.file.modify_date,
&ep->dentry.file.modify_time_cs);
ep->dentry.file.attr = cpu_to_le16(ei->attr);
/* File size should be zero if there is no cluster allocated */
if (ei->start_clu == EXFAT_EOF_CLUSTER) {
ep2->dentry.stream.valid_size = 0;
ep2->dentry.stream.size = 0;
} else {
ep2->dentry.stream.valid_size = cpu_to_le64(new_size);
ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
}
if (new_size == 0) {
/* Any directory can not be truncated to zero */
WARN_ON(ei->type != TYPE_FILE);
ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
}
exfat_update_dir_chksum_with_entry_set(es);
err = exfat_free_dentry_set(es, inode_needs_sync(inode));
if (err)
return err;
}
/* cut off from the FAT chain */ /* cut off from the FAT chain */
if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER && if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER &&

View File

@ -17,7 +17,7 @@
#include "exfat_raw.h" #include "exfat_raw.h"
#include "exfat_fs.h" #include "exfat_fs.h"
static int __exfat_write_inode(struct inode *inode, int sync) int __exfat_write_inode(struct inode *inode, int sync)
{ {
unsigned long long on_disk_size; unsigned long long on_disk_size;
struct exfat_dentry *ep, *ep2; struct exfat_dentry *ep, *ep2;
@ -75,6 +75,13 @@ 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;
if (on_disk_size) {
ep2->dentry.stream.flags = ei->flags;
ep2->dentry.stream.start_clu = cpu_to_le32(ei->start_clu);
} else {
ep2->dentry.stream.flags = ALLOC_FAT_CHAIN;
ep2->dentry.stream.start_clu = EXFAT_FREE_CLUSTER;
}
exfat_update_dir_chksum_with_entry_set(es); exfat_update_dir_chksum_with_entry_set(es);
return exfat_free_dentry_set(es, sync); return exfat_free_dentry_set(es, sync);
@ -216,32 +223,10 @@ 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 && modified) { if (modified) {
struct exfat_dentry *ep; if (__exfat_write_inode(inode, inode_needs_sync(inode)))
struct exfat_entry_set_cache *es;
int err;
es = exfat_get_dentry_set(sb, &(ei->dir), ei->entry,
ES_ALL_ENTRIES);
if (!es)
return -EIO; return -EIO;
/* get stream entry */ }
ep = exfat_get_dentry_cached(es, 1);
/* update directory entry */
ep->dentry.stream.flags = ei->flags;
ep->dentry.stream.start_clu =
cpu_to_le32(ei->start_clu);
ep->dentry.stream.valid_size =
cpu_to_le64(i_size_read(inode));
ep->dentry.stream.size =
ep->dentry.stream.valid_size;
exfat_update_dir_chksum_with_entry_set(es);
err = exfat_free_dentry_set(es, inode_needs_sync(inode));
if (err)
return err;
} /* end of if != DIR_DELETED */
inode->i_blocks += inode->i_blocks +=
num_to_be_allocated << sbi->sect_per_clus_bits; num_to_be_allocated << sbi->sect_per_clus_bits;

View File

@ -318,7 +318,6 @@ static int exfat_find_empty_entry(struct inode *inode,
unsigned int ret, last_clu; unsigned int ret, last_clu;
loff_t size = 0; loff_t size = 0;
struct exfat_chain clu; struct exfat_chain clu;
struct exfat_dentry *ep = 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);
@ -383,31 +382,16 @@ static int exfat_find_empty_entry(struct inode *inode,
p_dir->size++; p_dir->size++;
size = EXFAT_CLU_TO_B(p_dir->size, sbi); size = EXFAT_CLU_TO_B(p_dir->size, sbi);
/* update the directory entry */
if (p_dir->dir != sbi->root_dir) {
struct buffer_head *bh;
ep = exfat_get_dentry(sb,
&(ei->dir), ei->entry + 1, &bh);
if (!ep)
return -EIO;
ep->dentry.stream.valid_size = cpu_to_le64(size);
ep->dentry.stream.size = ep->dentry.stream.valid_size;
ep->dentry.stream.flags = p_dir->flags;
exfat_update_bh(bh, IS_DIRSYNC(inode));
brelse(bh);
if (exfat_update_dir_chksum(inode, &(ei->dir),
ei->entry))
return -EIO;
}
/* directory inode should be updated in here */ /* directory inode should be updated in here */
i_size_write(inode, size); i_size_write(inode, size);
ei->i_size_ondisk += sbi->cluster_size; ei->i_size_ondisk += sbi->cluster_size;
ei->i_size_aligned += sbi->cluster_size; ei->i_size_aligned += sbi->cluster_size;
ei->flags = p_dir->flags; ei->flags = p_dir->flags;
inode->i_blocks += 1 << sbi->sect_per_clus_bits; inode->i_blocks += 1 << sbi->sect_per_clus_bits;
/* update the directory entry */
if (__exfat_write_inode(inode, IS_DIRSYNC(inode)))
return -EIO;
} }
return dentry; return dentry;