Skip to content
Permalink
Browse files
exfat: aggregate dir-entry updates into __exfat_write_inode().
The following function writes the updated inode information as dir-entry
by themselves.
 - __exfat_truncate()
 - exfat_map_cluster()
 - exfat_find_empty_entry()
Aggregate these writes into __exfat_write_inode().

Also, in __exfat_write_inode(), rename 'on_disk_size' to 'filesize' and
add adjustment when filesize is 0.

Signed-off-by: Tetsuhiro Kohada <kohada.t2@gmail.com>
  • Loading branch information
Tetsuhiro Kohada authored and intel-lab-lkp committed Sep 18, 2020
1 parent f455c2a commit 605a79d44870ed9f396b6d5289fd1cecea3af8e3
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 96 deletions.
@@ -100,7 +100,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_inode_info *ei = EXFAT_I(inode);
int evict = (ei->dir.dir == DIR_DELETED) ? 1 : 0;
int ret;

/* check if the given file ID is opened */
if (ei->type != TYPE_FILE && ei->type != TYPE_DIR)
@@ -150,49 +150,10 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
ei->attr |= ATTR_ARCHIVE;

/* update the directory entry */
if (!evict) {
struct timespec64 ts;
struct exfat_dentry *ep, *ep2;
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;
}
inode->i_mtime = current_time(inode);
ret = exfat_update_inode(inode);
if (ret)
return ret;

/* cut off from the FAT chain */
if (ei->flags == ALLOC_FAT_CHAIN && last_clu != EXFAT_FREE_CLUSTER &&
@@ -19,7 +19,7 @@

static int __exfat_write_inode(struct inode *inode, int sync)
{
unsigned long long on_disk_size;
unsigned long long filesize;
struct exfat_dentry *ep, *ep2;
struct exfat_entry_set_cache *es = NULL;
struct super_block *sb = inode->i_sb;
@@ -68,13 +68,14 @@ static int __exfat_write_inode(struct inode *inode, int sync)
NULL);

/* File size should be zero if there is no cluster allocated */
on_disk_size = i_size_read(inode);

filesize = i_size_read(inode);
if (ei->start_clu == EXFAT_EOF_CLUSTER)
on_disk_size = 0;
filesize = 0;

ep2->dentry.stream.valid_size = cpu_to_le64(on_disk_size);
ep2->dentry.stream.valid_size = cpu_to_le64(filesize);
ep2->dentry.stream.size = ep2->dentry.stream.valid_size;
ep2->dentry.stream.flags = filesize ? ei->flags : ALLOC_FAT_CHAIN;
ep2->dentry.stream.start_clu = filesize ? ei->start_clu : EXFAT_FREE_CLUSTER;

exfat_update_dir_chksum_with_entry_set(es);
return exfat_free_dentry_set(es, sync);
@@ -223,32 +224,11 @@ static int exfat_map_cluster(struct inode *inode, unsigned int clu_offset,
num_clusters += num_to_be_allocated;
*clu = new_clu.dir;

if (ei->dir.dir != DIR_DELETED && modified) {
struct exfat_dentry *ep;
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;
/* 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 */
if (modified) {
ret = exfat_update_inode(inode);
if (ret)
return ret;
}

inode->i_blocks +=
num_to_be_allocated << sbi->sect_per_clus_bits;
@@ -306,10 +306,8 @@ static int exfat_find_empty_entry(struct inode *inode,
{
int dentry;
unsigned int ret, last_clu;
sector_t sector;
loff_t size = 0;
struct exfat_chain clu;
struct exfat_dentry *ep = NULL;
struct super_block *sb = inode->i_sb;
struct exfat_sb_info *sbi = EXFAT_SB(sb);
struct exfat_inode_info *ei = EXFAT_I(inode);
@@ -375,31 +373,17 @@ static int exfat_find_empty_entry(struct inode *inode,
p_dir->size++;
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, &sector);
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 */
i_size_write(inode, size);
EXFAT_I(inode)->i_size_ondisk += sbi->cluster_size;
EXFAT_I(inode)->i_size_aligned += sbi->cluster_size;
EXFAT_I(inode)->flags = p_dir->flags;
inode->i_blocks += 1 << sbi->sect_per_clus_bits;

/* update the directory entry */
ret = exfat_update_inode(inode);
if (ret)
return ret;
}

return dentry;

0 comments on commit 605a79d

Please sign in to comment.