f2fs: move release of block devices to after kill_block_super()
authorEric Biggers <ebiggers@google.com>
Wed, 27 Dec 2023 17:14:28 +0000 (11:14 -0600)
committerEric Biggers <ebiggers@google.com>
Thu, 28 Dec 2023 03:55:59 +0000 (21:55 -0600)
Call destroy_device_list() and free the f2fs_sb_info from
kill_f2fs_super(), after the call to kill_block_super().  This is
necessary to order it after the call to fscrypt_destroy_keyring() once
generic_shutdown_super() starts calling fscrypt_destroy_keyring() just
after calling ->put_super.  This is because fscrypt_destroy_keyring()
may call into f2fs_get_devices() via the fscrypt_operations.

Reviewed-by: Chao Yu <chao@kernel.org>
Link: https://lore.kernel.org/r/20231227171429.9223-2-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
fs/f2fs/super.c

index 033af907c3b1dc3059874fc689a32c0f0aaa45b2..d66e0692ac02eceda44a3bc6093b03ef66c5dc28 100644 (file)
@@ -1717,12 +1717,10 @@ static void f2fs_put_super(struct super_block *sb)
 
        kvfree(sbi->ckpt);
 
-       sb->s_fs_info = NULL;
        if (sbi->s_chksum_driver)
                crypto_free_shash(sbi->s_chksum_driver);
        kfree(sbi->raw_super);
 
-       destroy_device_list(sbi);
        f2fs_destroy_page_array_cache(sbi);
        f2fs_destroy_xattr_caches(sbi);
        mempool_destroy(sbi->write_io_dummy);
@@ -1738,7 +1736,6 @@ static void f2fs_put_super(struct super_block *sb)
 #if IS_ENABLED(CONFIG_UNICODE)
        utf8_unload(sb->s_encoding);
 #endif
-       kfree(sbi);
 }
 
 int f2fs_sync_fs(struct super_block *sb, int sync)
@@ -4902,9 +4899,9 @@ static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
 
 static void kill_f2fs_super(struct super_block *sb)
 {
-       if (sb->s_root) {
-               struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
 
+       if (sb->s_root) {
                set_sbi_flag(sbi, SBI_IS_CLOSE);
                f2fs_stop_gc_thread(sbi);
                f2fs_stop_discard_thread(sbi);
@@ -4931,6 +4928,12 @@ static void kill_f2fs_super(struct super_block *sb)
                        sb->s_flags &= ~SB_RDONLY;
        }
        kill_block_super(sb);
+       /* Release block devices last, after fscrypt_destroy_keyring(). */
+       if (sbi) {
+               destroy_device_list(sbi);
+               kfree(sbi);
+               sb->s_fs_info = NULL;
+       }
 }
 
 static struct file_system_type f2fs_fs_type = {