btrfs: set UNMAPPED bit early in btrfs_clone_extent_buffer() for subpage support
authorQu Wenruo <wqu@suse.com>
Tue, 26 Jan 2021 08:33:46 +0000 (16:33 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 8 Feb 2021 21:59:01 +0000 (22:59 +0100)
For the incoming subpage support, UNMAPPED extent buffer will have
different behavior in btrfs_release_extent_buffer().

This means we need to set UNMAPPED bit early before calling
btrfs_release_extent_buffer().

Currently there is only one caller which relies on
btrfs_release_extent_buffer() in its error path while set UNMAPPED bit
late:
- btrfs_clone_extent_buffer()

Make it subpage compatible by setting the UNMAPPED bit early, since
we're here, also move the UPTODATE bit early.

There is another caller, __alloc_dummy_extent_buffer(), setting
UNMAPPED bit late, but that function clean up the allocated page
manually, thus no need for any modification.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
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/extent_io.c

index 7c14ccf76838f1d8226c84e786bb01e684fb7e78..d3819dde895279565933ca78593abdfb31bca855 100644 (file)
@@ -5064,6 +5064,13 @@ struct extent_buffer *btrfs_clone_extent_buffer(const struct extent_buffer *src)
        if (new == NULL)
                return NULL;
 
+       /*
+        * Set UNMAPPED before calling btrfs_release_extent_buffer(), as
+        * btrfs_release_extent_buffer() have different behavior for
+        * UNMAPPED subpage extent buffer.
+        */
+       set_bit(EXTENT_BUFFER_UNMAPPED, &new->bflags);
+
        for (i = 0; i < num_pages; i++) {
                p = alloc_page(GFP_NOFS);
                if (!p) {
@@ -5076,9 +5083,7 @@ struct extent_buffer *btrfs_clone_extent_buffer(const struct extent_buffer *src)
                new->pages[i] = p;
                copy_page(page_address(p), page_address(src->pages[i]));
        }
-
        set_bit(EXTENT_BUFFER_UPTODATE, &new->bflags);
-       set_bit(EXTENT_BUFFER_UNMAPPED, &new->bflags);
 
        return new;
 }