aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuezhang Mo <Yuezhang.Mo@sony.com>2022-03-19 11:08:03 +0900
committerNamjae Jeon <linkinjeon@kernel.org>2022-04-01 10:51:03 +0900
commita4a3d8c52d952ab1f5c8b8b67b57f2e01936628d (patch)
tree7c60133f7d4c1e570978bc4ad5bd0df8b44d484f
parent9ec784bf774c2d3b35a7577fc6441cfbd60aefea (diff)
downloadlinux-a4a3d8c52d952ab1f5c8b8b67b57f2e01936628d.tar.gz
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: 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>
-rw-r--r--fs/exfat/file.c2
-rw-r--r--fs/exfat/namei.c5
-rw-r--r--fs/exfat/super.c10
3 files changed, 2 insertions, 15 deletions
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index d890fd34bb2d04..2f513005923661 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -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;
}
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index a4f8010fbd38e6..a02a04a993bfa9 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -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;
}
diff --git a/fs/exfat/super.c b/fs/exfat/super.c
index 4c3f80ed17b1ef..381b9100edca08 100644
--- a/fs/exfat/super.c
+++ b/fs/exfat/super.c
@@ -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;
}