Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e92aaf1b authored by Namjae Jeon's avatar Namjae Jeon
Browse files

exfat: do not clear VolumeDirty in writeback



Before this commit, VolumeDirty will be cleared first in
writeback if 'dirsync' or 'sync' is not enabled. If the power
is suddenly cut off after cleaning VolumeDirty but other
updates are not written, the exFAT filesystem will not be able
to detect the power failure in the next mount.

And VolumeDirty will be set again but not cleared when updating
the parent directory. It means that BootSector will be written at
least once in each write-back, which will shorten the life of the
device.

Reviewed-by: default avatarAndy Wu <Andy.Wu@sony.com>
Reviewed-by: default avatarAoyama Wataru <wataru.aoyama@sony.com>
Signed-off-by: default avatarYuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
parent 531f58fc
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -233,8 +233,6 @@ int __exfat_truncate(struct inode *inode, loff_t new_size)
	if (exfat_free_cluster(inode, &clu))
		return -EIO;

	exfat_clear_volume_dirty(sb);

	return 0;
}

+0 −5
Original line number Diff line number Diff line
@@ -608,7 +608,6 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
	exfat_set_volume_dirty(sb);
	err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_FILE,
		&info);
	exfat_clear_volume_dirty(sb);
	if (err)
		goto unlock;

@@ -896,7 +895,6 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)

	/* This doesn't modify ei */
	ei->dir.dir = DIR_DELETED;
	exfat_clear_volume_dirty(sb);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
	inode_inc_iversion(dir);
@@ -950,7 +948,6 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
	exfat_set_volume_dirty(sb);
	err = exfat_add_entry(dir, dentry->d_name.name, &cdir, TYPE_DIR,
		&info);
	exfat_clear_volume_dirty(sb);
	if (err)
		goto unlock;

@@ -1098,7 +1095,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
		goto unlock;
	}
	ei->dir.dir = DIR_DELETED;
	exfat_clear_volume_dirty(sb);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
	inode_inc_iversion(dir);
@@ -1449,7 +1445,6 @@ static int __exfat_rename(struct inode *old_parent_inode,
		 */
		new_ei->dir.dir = DIR_DELETED;
	}
	exfat_clear_volume_dirty(sb);
out:
	return ret;
}
+6 −8
Original line number Diff line number Diff line
@@ -113,7 +113,6 @@ static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flags)
{
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	struct boot_sector *p_boot = (struct boot_sector *)sbi->boot_bh->b_data;
	bool sync;

	/* retain persistent-flags */
	new_flags |= sbi->vol_flags_persistent;
@@ -136,16 +135,15 @@ static int exfat_set_vol_flags(struct super_block *sb, unsigned short new_flags)

	p_boot->vol_flags = cpu_to_le16(new_flags);

	if ((new_flags & VOLUME_DIRTY) && !buffer_dirty(sbi->boot_bh))
		sync = true;
	else
		sync = false;

	set_buffer_uptodate(sbi->boot_bh);
	mark_buffer_dirty(sbi->boot_bh);

	if (sync)
		sync_dirty_buffer(sbi->boot_bh);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
	__sync_dirty_buffer(sbi->boot_bh, REQ_SYNC | REQ_FUA | REQ_PREFLUSH);
#else
	__sync_dirty_buffer(sbi->boot_bh, REQ_SYNC | REQ_FUA | REQ_FLUSH);
#endif

	return 0;
}