__ext4_remount() refuses any change of the read-only state with -EROFS while ext4_emergency_state() is set, i.e. after FS_IOC_SHUTDOWN, after an error with errors=remount-ro or after an error that forces the filesystem read-only like ext4_abort(). None of them sets SB_RDONLY anymore. So a plain remount to read-only fails and the filesystem stays read-write. And emergency remount (sysrq u) asks every read-write superblock on a block device to go read-only with SB_FORCE. ext4 refuses that too and reconfigure_super() warns before it sets SB_RDONLY anyway: EXT4-fs (vda): Remounting filesystem read-only sysrq: Emergency Remount R/O forced remount of a ext4 fs returned -30 WARNING: fs/super.c:1133 at reconfigure_super+0x498/0xb20, CPU#3: kworker/3:1/50 do_emergency_remount_callback+0xc4/0x100 __iterate_supers+0x33d/0x410 do_emergency_remount+0x20/0x40 With panic_on_warn that's a panic from sysrq u. Nothing may be written in the emergency state but becoming read-only doesn't need to write anything. So allow going read-only and skip everything in that branch that would touch the disk. That's sync_filesystem(), which fails with the emergency errno anyway, dquot_suspend(), the s_state update and ext4_mark_recovery_complete(). Note that after a shutdown with FS_SHUTDOWN_FLAGS_DEFAULT the journal is still live and the latter would really write. Also skip the superblock commit a remount does for a filesystem without a journal, like ext4_put_super() does in that state. Going read-write is still refused with -EROFS and option-only remounts work as before. Quotas stay on until umount. That's the rule the filesystems converted earlier in this series follow as well. In the emergency state going read-write fails and going read-only works, writing at most what was dirtied before the error. Reproducer (the sb_rdonly selftest after this patch covers the mount(2) path): truncate -s 64M img; mkfs.ext4 -q img mount -o loop,errors=remount-ro img /mnt xfs_io -x -c shutdown /mnt # or any ext4 error, e.g. # echo x > /sys/fs/ext4/loop0/trigger_fs_error mount -o remount,ro /mnt # EROFS, stays read-write echo u > /proc/sysrq-trigger # WARNING: forced remount of a ext4 fs returned -30 Fixes: 95257987a638 ("ext4: drop EXT4_MF_FS_ABORTED flag") Fixes: d3476f3dad4a ("ext4: don't set SB_RDONLY after filesystem errors") Cc: stable@vger.kernel.org Signed-off-by: Christian Brauner (Amutable) --- fs/ext4/super.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d636b89090a2..643c304460ec 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -6711,11 +6711,18 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb) if ((bool)(fc->sb_flags & SB_RDONLY) != sb_rdonly(sb)) { if (ext4_emergency_state(sb)) { - err = -EROFS; - goto restore_opts; - } - - if (fc->sb_flags & SB_RDONLY) { + /* + * Nothing may be written in the emergency state. Going + * read-write stays refused, but going read-only must + * not fail or emergency remount (sysrq u) WARNs. So + * just become read-only without touching the disk. + */ + if (!(fc->sb_flags & SB_RDONLY)) { + err = -EROFS; + goto restore_opts; + } + sb->s_flags |= SB_RDONLY; + } else if (fc->sb_flags & SB_RDONLY) { err = sync_filesystem(sb); if (err < 0) goto restore_opts; @@ -6826,7 +6833,8 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb) goto restore_opts; } - if (sbi->s_journal == NULL && !(old_sb_flags & SB_RDONLY)) { + if (sbi->s_journal == NULL && !(old_sb_flags & SB_RDONLY) && + !ext4_emergency_state(sb)) { err = ext4_commit_super(sb); if (err) goto restore_opts; -- 2.53.0