update sb->s_frozen when freezing read-only mounted device, too
PATCH 1/1 update sb->s_frozen when freezing read-only mounted device, too
freeze_bdev() with the device which is mounted as read only does not change sb->s_frozen from SB_UNFROZEN to SB_FREEZE_TRANS.
Because of this behavior, xfs_freeze can break read-only XFS filesystem.
Because xfs_thaw does nothing for the filesystem whose sb->s_frozen is SB_UNFROZEN. So freezed readonly XFS filesystem will never be unfreezed. Then we cannot do any unmount/remount operations for that filesystem.
This patch updates sb->s_frozen when freeze_bdev() is called for read-only mounted device, too.
--- fs/buffer.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
fs/buffer.c +8 -5
@@ -190,19 +190,22 @@ struct super_block *freeze_bdev(struct bdown (&bdev->bd_mount_sem); sb =get_super (bdev); -if (sb && !(sb->s_flags &MS_RDONLY )) { +if (sb) { sb->s_frozen =SB_FREEZE_WRITE ;smp_wmb (); -__fsync_super (sb); +if (!(sb->s_flags &MS_RDONLY )) +__fsync_super (sb); sb->s_frozen =SB_FREEZE_TRANS ;smp_wmb (); -sync_blockdev (sb->s_bdev); +if (!(sb->s_flags &MS_RDONLY )) { +sync_blockdev (sb->s_bdev); -if (sb->s_op->write_super_lockfs) - sb->s_op->write_super_lockfs (sb); +if (sb->s_op->write_super_lockfs) + sb->s_op->write_super_lockfs (sb); + } }sync_blockdev (bdev);
Quoted 11 lines · Akinobu Mita
freeze_bdev()with the device which is mounted as read only does not changesb->s_frozenfromSB_UNFROZENtoSB_FREEZE_TRANS.Because of this behavior,
xfs_freezecan break read-only XFS filesystem.Because
xfs_thawdoes nothing for the filesystem whosesb->s_frozenisSB_UNFROZEN. So freezed readonly XFS filesystem will never be unfreezed. Then we cannot do any unmount/remount operations for that filesystem.This patch updates
sb->s_frozenwhenfreeze_bdev()is called for read-only mounted device, too.
I think this fix is valid, but it might be a tad cleaner to just set s_frozen to SB_FREEZE_TRANS directly in a separate branch, ala:
struct super_block *freeze_bdev(struct block_device *bdev)
{
struct super_block *sb;
down(&bdev->bd_mount_sem);
sb = get_super(bdev);
if (!sb)
goto out;
if (sb->s_flags & MS_RDONLY) {
sb->s_frozen = SB_FREEZE_TRANS;
smp_wmb();
goto out;
}
sb->s_frozen = SB_FREEZE_WRITE;
smp_wmb();
__fsync_super(sb);
sb->s_frozen = SB_FREEZE_TRANS
smp_wmb();
sync_blockdev(sb->s_bdev);
if (sb->s_op->write_super_lockfs)
sb->s_op->write_super_lockfs(sb);out:
sync_blockdev(bdev); return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */ }
2007/10/5, Christoph Hellwig <[email protected]>:
Quoted 10 lines · Akinobu Mita
Quoted 9 lines
freeze_bdev()with the device which is mounted as read only does not changesb->s_frozenfromSB_UNFROZENtoSB_FREEZE_TRANS.Because of this behavior,
xfs_freezecan break read-only XFS filesystem.Because
xfs_thawdoes nothing for the filesystem whosesb->s_frozenisSB_UNFROZEN. So freezed readonly XFS filesystem will never be unfreezed. Then we cannot do any unmount/remount operations for that filesystem.
Quoted 5 lines
Quoted 2 lines
This patch updates
sb->s_frozenwhenfreeze_bdev()is called for read-only mounted device, too.I think this fix is valid, but it might be a tad cleaner to just set
s_frozentoSB_FREEZE_TRANSdirectly in a separate branch, ala:
It looks cleaner than mine. I'll resubmit it.
Quoted 33 lines
struct
super_block*freeze_bdev(structblock_device*bdev){ struct super_block *sb; down(&bdev->bd_mount_sem); sb = get_super(bdev); if (!sb) goto out; if (sb->s_flags & MS_RDONLY) { sb->s_frozen = SB_FREEZE_TRANS; smp_wmb(); goto out; } sb->s_frozen = SB_FREEZE_WRITE; smp_wmb(); __fsync_super(sb); sb->s_frozen = SB_FREEZE_TRANS smp_wmb(); sync_blockdev(sb->s_bdev); if (sb->s_op->write_super_lockfs) sb->s_op->write_super_lockfs(sb);out:
sync_blockdev(bdev); return sb; /* thaw_bdev releases s->s_umount and bd_mount_sem */ }
freeze_bdev() with read-only mounted device(*) does not change sb->s_frozen from SB_UNFROZEN to SB_FREEZE_TRANS.
Because of this behavior, xfs_freeze can break read-only filesystem.
Because xfs_thaw does nothing for the filesystem whose sb->s_frozen is SB_UNFROZEN. So frozen read-only XFS filesystem will never be unfrozen. Thus we cannot do any unmount/remount operations for that filesystem.
This patch updates sb->s_frozen when freeze_bdev() is called for read-only mounted device, too.
(*) freezing read-only filesystem is not so pointless. Because it can prevent from someone trying to remount read/write while freezing.
--- fs/buffer.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
fs/buffer.c +16 -9
@@ -190,21 +190,28 @@ struct super_block *freeze_bdev(struct bdown (&bdev->bd_mount_sem); sb =get_super (bdev); -if (sb && !(sb->s_flags &MS_RDONLY )) { - sb->s_frozen =SB_FREEZE_WRITE ; -smp_wmb (); - -__fsync_super (sb); +if (!sb) + goto out; +if (sb->s_flags &MS_RDONLY ) { sb->s_frozen =SB_FREEZE_TRANS ;smp_wmb (); + goto out; + } -sync_blockdev (sb->s_bdev); + sb->s_frozen =SB_FREEZE_WRITE ; +smp_wmb (); -if (sb->s_op->write_super_lockfs) - sb->s_op->write_super_lockfs (sb); - } +__fsync_super (sb); + + sb->s_frozen =SB_FREEZE_TRANS ; +smp_wmb (); +sync_blockdev (sb->s_bdev); + +if (sb->s_op->write_super_lockfs) + sb->s_op->write_super_lockfs (sb); +out:sync_blockdev (bdev);return sb;/* thaw_bdev releases s->s_umount and bd_mount_sem */ }