exfat: do not clear VolumeDirty in writeback
authorYuezhang Mo <Yuezhang.Mo@sony.com>
Sat, 19 Mar 2022 02:08:03 +0000 (11:08 +0900)
committerNamjae Jeon <linkinjeon@kernel.org>
Fri, 1 Apr 2022 01:51:03 +0000 (10:51 +0900)
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: Andy Wu <Andy.Wu@sony.com>
Reviewed-by: Aoyama Wataru <wataru.aoyama@sony.com>
Signed-off-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/exfat/file.c
fs/exfat/namei.c
fs/exfat/super.c

index d890fd34bb2d040a9c5c34939964a847f8a25c16..2f513005923661d4962817b7b6531f1b6548b7da 100644 (file)
@@ -218,8 +218,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;
 }
 
index a4f8010fbd38e61664ce87411b5c02ba4a8be0bb..a02a04a993bfa9cccb3632538f8c97dc8ef84427 100644 (file)
@@ -576,7 +576,6 @@ static int exfat_create(struct user_namespace *mnt_userns, struct inode *dir,
        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;
 
@@ -834,7 +833,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);
 
        inode_inc_iversion(dir);
        dir->i_mtime = dir->i_atime = current_time(dir);
@@ -868,7 +866,6 @@ static int exfat_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
        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;
 
@@ -998,7 +995,6 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
                goto unlock;
        }
        ei->dir.dir = DIR_DELETED;
-       exfat_clear_volume_dirty(sb);
 
        inode_inc_iversion(dir);
        dir->i_mtime = dir->i_atime = current_time(dir);
@@ -1333,7 +1329,6 @@ del_out:
                 */
                new_ei->dir.dir = DIR_DELETED;
        }
-       exfat_clear_volume_dirty(sb);
 out:
        return ret;
 }
index 4c3f80ed17b1efcdea9ac0a43b280ab52254f882..381b9100edca08af85c8ada57f0c1913f7c0fe43 100644 (file)
@@ -100,7 +100,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;
@@ -119,16 +118,11 @@ 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);
+       __sync_dirty_buffer(sbi->boot_bh, REQ_SYNC | REQ_FUA | REQ_PREFLUSH);
+
        return 0;
 }