btrfs: use dummy extent buffer for super block sys chunk array read
authorQu Wenruo <wqu@suse.com>
Thu, 13 Jan 2022 05:22:08 +0000 (13:22 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:03:10 +0000 (17:03 +0200)
In function btrfs_read_sys_array(), we allocate a real extent buffer
using btrfs_find_create_tree_block().

Such extent buffer will be even cached into buffer_radix tree, and using
btree inode address space.

However we only use such extent buffer to enable the accessors, thus we
don't even need to bother using real extent buffer, a dummy one is
what we really need.

And for dummy extent buffer, we no longer need to do any special
handling for the first page, as subpage helper is already doing it
properly.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index 3471698..04809d4 100644 (file)
@@ -7370,7 +7370,6 @@ static int read_one_dev(struct extent_buffer *leaf,
 
 int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
 {
-       struct btrfs_root *root = fs_info->tree_root;
        struct btrfs_super_block *super_copy = fs_info->super_copy;
        struct extent_buffer *sb;
        struct btrfs_disk_key *disk_key;
@@ -7386,30 +7385,16 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
        struct btrfs_key key;
 
        ASSERT(BTRFS_SUPER_INFO_SIZE <= fs_info->nodesize);
+
        /*
-        * This will create extent buffer of nodesize, superblock size is
-        * fixed to BTRFS_SUPER_INFO_SIZE. If nodesize > sb size, this will
-        * overallocate but we can keep it as-is, only the first page is used.
+        * We allocated a dummy extent, just to use extent buffer accessors.
+        * There will be unused space after BTRFS_SUPER_INFO_SIZE, but
+        * that's fine, we will not go beyond system chunk array anyway.
         */
-       sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET,
-                                         root->root_key.objectid, 0);
-       if (IS_ERR(sb))
-               return PTR_ERR(sb);
+       sb = alloc_dummy_extent_buffer(fs_info, BTRFS_SUPER_INFO_OFFSET);
+       if (!sb)
+               return -ENOMEM;
        set_extent_buffer_uptodate(sb);
-       /*
-        * The sb extent buffer is artificial and just used to read the system array.
-        * set_extent_buffer_uptodate() call does not properly mark all it's
-        * pages up-to-date when the page is larger: extent does not cover the
-        * whole page and consequently check_page_uptodate does not find all
-        * the page's extents up-to-date (the hole beyond sb),
-        * write_extent_buffer then triggers a WARN_ON.
-        *
-        * Regular short extents go through mark_extent_buffer_dirty/writeback cycle,
-        * but sb spans only this function. Add an explicit SetPageUptodate call
-        * to silence the warning eg. on PowerPC 64.
-        */
-       if (PAGE_SIZE > BTRFS_SUPER_INFO_SIZE)
-               SetPageUptodate(sb->pages[0]);
 
        write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
        array_size = btrfs_super_sys_array_size(super_copy);