Re: [PATCH] exfat: do not clear VolumeDirty in writeback
From: Namjae Jeon
Date: Sat Mar 05 2022 - 01:03:55 EST
2022-02-08 14:18 GMT+09:00, Yuezhang.Mo@xxxxxxxx <Yuezhang.Mo@xxxxxxxx>:
Hi Yuezhang,
> 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 when updating the parent
> directory. It means that BootSector will be written twice in each
> writeback, that will shorten the life of the device.
>
> Reviewed-by: Andy.Wu <Andy.Wu@xxxxxxxx>
> Reviewed-by: Aoyama, Wataru <wataru.aoyama@xxxxxxxx>
> Signed-off-by: Yuezhang.Mo <Yuezhang.Mo@xxxxxxxx>
> ---
> fs/exfat/super.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/fs/exfat/super.c b/fs/exfat/super.c
> index 8c9fb7dcec16..f4906c17475e 100644
> --- a/fs/exfat/super.c
> +++ b/fs/exfat/super.c
> @@ -25,6 +25,8 @@
> static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET;
> static struct kmem_cache *exfat_inode_cachep;
>
> +static int __exfat_clear_volume_dirty(struct super_block *sb);
> +
> static void exfat_free_iocharset(struct exfat_sb_info *sbi)
> {
> if (sbi->options.iocharset != exfat_default_iocharset)
> @@ -64,7 +66,7 @@ static int exfat_sync_fs(struct super_block *sb, int wait)
> /* If there are some dirty buffers in the bdev inode */
> mutex_lock(&sbi->s_lock);
> sync_blockdev(sb->s_bdev);
> - if (exfat_clear_volume_dirty(sb))
> + if (__exfat_clear_volume_dirty(sb))
> err = -EIO;
> mutex_unlock(&sbi->s_lock);
> return err;
> @@ -139,13 +141,21 @@ int exfat_set_volume_dirty(struct super_block *sb)
> return exfat_set_vol_flags(sb, sbi->vol_flags | VOLUME_DIRTY);
> }
>
> -int exfat_clear_volume_dirty(struct super_block *sb)
> +static int __exfat_clear_volume_dirty(struct super_block *sb)
> {
> struct exfat_sb_info *sbi = EXFAT_SB(sb);
>
> return exfat_set_vol_flags(sb, sbi->vol_flags & ~VOLUME_DIRTY);
> }
>
> +int exfat_clear_volume_dirty(struct super_block *sb)
> +{
> + if (sb->s_flags & (SB_SYNCHRONOUS | SB_DIRSYNC))
How about moving exfat_clear_volume_dirty() to IS_DIRSYNC() check in
each operations instead of this check?
> + return __exfat_clear_volume_dirty(sb);
> +
> + return 0;
> +}
> +
> static int exfat_show_options(struct seq_file *m, struct dentry *root)
> {
> struct super_block *sb = root->d_sb;
> --
> 2.25.1