Commit 4493895b authored by Yuezhang Mo's avatar Yuezhang Mo Committed by Namjae Jeon
Browse files

exfat: remove duplicate write inode for truncating file



This commit moves updating file attributes and timestamps before
calling __exfat_write_inode(), so that all updates of the inode
had been written by __exfat_write_inode(), mark_inode_dirty() is
unneeded.

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 avatarDaniel Palmer <daniel.palmer@sony.com>
Reviewed-by: default avatarSungjong Seo <sj1557.seo@samsung.com>
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
parent 23e6e1c9
Loading
Loading
Loading
Loading
+24 −13
Original line number Diff line number Diff line
@@ -148,8 +148,17 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
	if (ei->type == TYPE_FILE)
		ei->attr |= ATTR_ARCHIVE;

	/* update the directory entry */
	inode->i_mtime = current_time(inode);
	/*
	 * update the directory entry
	 *
	 * If the directory entry is updated by mark_inode_dirty(), the
	 * directory entry will be written after a writeback cycle of
	 * updating the bitmap/FAT, which may result in clusters being
	 * freed but referenced by the directory entry in the event of a
	 * sudden power failure.
	 * __exfat_write_inode() is called for directory entry, bitmap
	 * and FAT to be written in a same writeback.
	 */
	if (__exfat_write_inode(inode, inode_needs_sync(inode)))
		return -EIO;

@@ -202,12 +211,6 @@ void exfat_truncate(struct inode *inode, loff_t size)
	if (err)
		goto write_size;

	inode->i_ctime = inode->i_mtime = current_time(inode);
	if (IS_DIRSYNC(inode))
		exfat_sync_inode(inode);
	else
		mark_inode_dirty(inode);

	inode->i_blocks = round_up(i_size_read(inode), sbi->cluster_size) >>
				inode->i_blkbits;
write_size:
@@ -289,6 +292,12 @@ int exfat_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
			attr->ia_valid &= ~ATTR_MODE;
	}

	if (attr->ia_valid & ATTR_SIZE)
		inode->i_mtime = inode->i_ctime = current_time(inode);

	setattr_copy(&init_user_ns, inode, attr);
	exfat_truncate_atime(&inode->i_atime);

	if (attr->ia_valid & ATTR_SIZE) {
		error = exfat_block_truncate_page(inode, attr->ia_size);
		if (error)
@@ -296,12 +305,14 @@ int exfat_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,

		down_write(&EXFAT_I(inode)->truncate_lock);
		truncate_setsize(inode, attr->ia_size);

		/*
		 * __exfat_write_inode() is called from exfat_truncate(), inode
		 * is already written by it, so mark_inode_dirty() is unneeded.
		 */
		exfat_truncate(inode, attr->ia_size);
		up_write(&EXFAT_I(inode)->truncate_lock);
	}

	setattr_copy(&init_user_ns, inode, attr);
	exfat_truncate_atime(&inode->i_atime);
	} else
		mark_inode_dirty(inode);

out:
+1 −0
Original line number Diff line number Diff line
@@ -369,6 +369,7 @@ static void exfat_write_failed(struct address_space *mapping, loff_t to)

	if (to > i_size_read(inode)) {
		truncate_pagecache(inode, i_size_read(inode));
		inode->i_mtime = inode->i_ctime = current_time(inode);
		exfat_truncate(inode, EXFAT_I(inode)->i_size_aligned);
	}
}