Skip to content

Commit ea7b3e6

Browse files
committed
Merge tag 'vfs-5.17-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull vfs fixes from Darrick Wong: "I was auditing the sync_fs code paths recently and noticed that most callers of ->sync_fs ignore its return value (and many implementations never return nonzero even if the fs is broken!), which means that internal fs errors and corruption are not passed up to userspace callers of syncfs(2) or FIFREEZE. Hence fixing the common code and XFS, and I'll start working on the ext4/btrfs folks if this is merged. Summary: - Fix a bug where callers of ->sync_fs (e.g. sync_filesystem and syncfs(2)) ignore the return value. - Fix a bug where callers of sync_filesystem (e.g. fs freeze) ignore the return value. - Fix a bug in XFS where xfs_fs_sync_fs never passed back error returns" * tag 'vfs-5.17-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: return errors in xfs_fs_sync_fs quota: make dquot_quota_sync return errors from ->sync_fs vfs: make sync_filesystem return errors from ->sync_fs vfs: make freeze_super abort when sync_filesystem returns error
2 parents 524446e + 2d86293 commit ea7b3e6

File tree

4 files changed

+37
-17
lines changed

4 files changed

+37
-17
lines changed

fs/quota/dquot.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -690,9 +690,14 @@ int dquot_quota_sync(struct super_block *sb, int type)
690690
/* This is not very clever (and fast) but currently I don't know about
691691
* any other simple way of getting quota data to disk and we must get
692692
* them there for userspace to be visible... */
693-
if (sb->s_op->sync_fs)
694-
sb->s_op->sync_fs(sb, 1);
695-
sync_blockdev(sb->s_bdev);
693+
if (sb->s_op->sync_fs) {
694+
ret = sb->s_op->sync_fs(sb, 1);
695+
if (ret)
696+
return ret;
697+
}
698+
ret = sync_blockdev(sb->s_bdev);
699+
if (ret)
700+
return ret;
696701

697702
/*
698703
* Now when everything is written we can discard the pagecache so

fs/super.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,11 +1616,9 @@ static void lockdep_sb_freeze_acquire(struct super_block *sb)
16161616
percpu_rwsem_acquire(sb->s_writers.rw_sem + level, 0, _THIS_IP_);
16171617
}
16181618

1619-
static void sb_freeze_unlock(struct super_block *sb)
1619+
static void sb_freeze_unlock(struct super_block *sb, int level)
16201620
{
1621-
int level;
1622-
1623-
for (level = SB_FREEZE_LEVELS - 1; level >= 0; level--)
1621+
for (level--; level >= 0; level--)
16241622
percpu_up_write(sb->s_writers.rw_sem + level);
16251623
}
16261624

@@ -1691,7 +1689,14 @@ int freeze_super(struct super_block *sb)
16911689
sb_wait_write(sb, SB_FREEZE_PAGEFAULT);
16921690

16931691
/* All writers are done so after syncing there won't be dirty data */
1694-
sync_filesystem(sb);
1692+
ret = sync_filesystem(sb);
1693+
if (ret) {
1694+
sb->s_writers.frozen = SB_UNFROZEN;
1695+
sb_freeze_unlock(sb, SB_FREEZE_PAGEFAULT);
1696+
wake_up(&sb->s_writers.wait_unfrozen);
1697+
deactivate_locked_super(sb);
1698+
return ret;
1699+
}
16951700

16961701
/* Now wait for internal filesystem counter */
16971702
sb->s_writers.frozen = SB_FREEZE_FS;
@@ -1703,7 +1708,7 @@ int freeze_super(struct super_block *sb)
17031708
printk(KERN_ERR
17041709
"VFS:Filesystem freeze failed\n");
17051710
sb->s_writers.frozen = SB_UNFROZEN;
1706-
sb_freeze_unlock(sb);
1711+
sb_freeze_unlock(sb, SB_FREEZE_FS);
17071712
wake_up(&sb->s_writers.wait_unfrozen);
17081713
deactivate_locked_super(sb);
17091714
return ret;
@@ -1748,7 +1753,7 @@ static int thaw_super_locked(struct super_block *sb)
17481753
}
17491754

17501755
sb->s_writers.frozen = SB_UNFROZEN;
1751-
sb_freeze_unlock(sb);
1756+
sb_freeze_unlock(sb, SB_FREEZE_FS);
17521757
out:
17531758
wake_up(&sb->s_writers.wait_unfrozen);
17541759
deactivate_locked_super(sb);

fs/sync.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*/
3030
int sync_filesystem(struct super_block *sb)
3131
{
32-
int ret;
32+
int ret = 0;
3333

3434
/*
3535
* We need to be protected against the filesystem going from
@@ -52,15 +52,21 @@ int sync_filesystem(struct super_block *sb)
5252
* at a time.
5353
*/
5454
writeback_inodes_sb(sb, WB_REASON_SYNC);
55-
if (sb->s_op->sync_fs)
56-
sb->s_op->sync_fs(sb, 0);
55+
if (sb->s_op->sync_fs) {
56+
ret = sb->s_op->sync_fs(sb, 0);
57+
if (ret)
58+
return ret;
59+
}
5760
ret = sync_blockdev_nowait(sb->s_bdev);
58-
if (ret < 0)
61+
if (ret)
5962
return ret;
6063

6164
sync_inodes_sb(sb);
62-
if (sb->s_op->sync_fs)
63-
sb->s_op->sync_fs(sb, 1);
65+
if (sb->s_op->sync_fs) {
66+
ret = sb->s_op->sync_fs(sb, 1);
67+
if (ret)
68+
return ret;
69+
}
6470
return sync_blockdev(sb->s_bdev);
6571
}
6672
EXPORT_SYMBOL(sync_filesystem);

fs/xfs/xfs_super.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ xfs_fs_sync_fs(
735735
int wait)
736736
{
737737
struct xfs_mount *mp = XFS_M(sb);
738+
int error;
738739

739740
trace_xfs_fs_sync_fs(mp, __return_address);
740741

@@ -744,7 +745,10 @@ xfs_fs_sync_fs(
744745
if (!wait)
745746
return 0;
746747

747-
xfs_log_force(mp, XFS_LOG_SYNC);
748+
error = xfs_log_force(mp, XFS_LOG_SYNC);
749+
if (error)
750+
return error;
751+
748752
if (laptop_mode) {
749753
/*
750754
* The disk must be active because we're syncing.

0 commit comments

Comments
 (0)