diff --git a/fs/super.c b/fs/super.c index b142e71eb8df..f8fe07501c9f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1217,16 +1217,24 @@ void emergency_remount(void) static void do_thaw_all_callback(struct super_block *sb) { - bool born = super_lock_excl(sb); + bool active = false; - if (born && sb->s_root) { - if (IS_ENABLED(CONFIG_BLOCK)) - while (sb->s_bdev && !thaw_bdev(sb->s_bdev)) - pr_warn("Emergency Thaw on %pg\n", sb->s_bdev); + if (super_lock_excl(sb)) + active = atomic_inc_not_zero(&sb->s_active); + super_unlock_excl(sb); + if (!active) + return; + + /* thaw_bdev() acquires s_umount so it must not be held here */ + if (IS_ENABLED(CONFIG_BLOCK)) + while (sb->s_bdev && !thaw_bdev(sb->s_bdev)) + pr_warn("Emergency Thaw on %pg\n", sb->s_bdev); + + if (super_lock_excl(sb)) thaw_super_locked(sb, FREEZE_HOLDER_USERSPACE); - } else { + else super_unlock_excl(sb); - } + deactivate_super(sb); } static void do_thaw_all(struct work_struct *work)