]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: only invalidate btree inode pages after all ebs are released
authorQu Wenruo <wqu@suse.com>
Mon, 30 Mar 2026 22:21:56 +0000 (08:51 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 16:56:08 +0000 (18:56 +0200)
In close_ctree(), we call invalidate_inode_pages2() to invalidate all
pages from btree inode.

But the problem is, it never returns 0, but always -EBUSY.

The problem is that we are still holding all the essential tree root
nodes, thus pages holding those tree blocks can not be invalidated thus
invalidate_inode_pages2() always returns -EBUSY.

This is also against the error cleanup path of open_ctree(), which
properly frees all root pointers before calling invalidate_inode_pages().

So fix the order by delaying invalidate_inode_pages2() until we have
freed all root pointers.

Reviewed-by: Anand Jain <asj@kernel.org>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/disk-io.c

index c835141ee384fdfdc719f93264a94f8644962975..14ce9bfc981be0d8cb776324a0305b424f2d37a5 100644 (file)
@@ -4434,13 +4434,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
 
        btrfs_put_block_group_cache(fs_info);
 
-       /*
-        * we must make sure there is not any read request to
-        * submit after we stopping all workers.
-        */
-       invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
-       btrfs_stop_all_workers(fs_info);
-
        /* We shouldn't have any transaction open at this point */
        warn_about_uncommitted_trans(fs_info);
 
@@ -4448,6 +4441,13 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        free_root_pointers(fs_info, true);
        btrfs_free_fs_roots(fs_info);
 
+       /*
+        * We must make sure there is not any read request to
+        * submit after we stop all workers.
+        */
+       invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
+       btrfs_stop_all_workers(fs_info);
+
        /*
         * We must free the block groups after dropping the fs_roots as we could
         * have had an IO error and have left over tree log blocks that aren't