There are locations where we allocate dummy extent buffers for temporary
usage, like in tree_mod_log_rewind() or get_old_root().

These dummy extent buffers will be handled by the same eb accessors, and
if they don't have page::private subpage eb accessors could fail.

To address such problems, make __alloc_dummy_extent_buffer() attach
page private for dummy extent buffers too.

Signed-off-by: Qu Wenruo <w...@suse.com>
Reviewed-by: David Sterba <dste...@suse.com>
Signed-off-by: David Sterba <dste...@suse.com>
---
 fs/btrfs/extent_io.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 118874926179..7ee28d94bae9 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5183,9 +5183,14 @@ struct extent_buffer *__alloc_dummy_extent_buffer(struct 
btrfs_fs_info *fs_info,
 
        num_pages = num_extent_pages(eb);
        for (i = 0; i < num_pages; i++) {
+               int ret;
+
                eb->pages[i] = alloc_page(GFP_NOFS);
                if (!eb->pages[i])
                        goto err;
+               ret = attach_extent_buffer_page(eb, eb->pages[i], NULL);
+               if (ret < 0)
+                       goto err;
        }
        set_extent_buffer_uptodate(eb);
        btrfs_set_header_nritems(eb, 0);
@@ -5193,8 +5198,10 @@ struct extent_buffer *__alloc_dummy_extent_buffer(struct 
btrfs_fs_info *fs_info,
 
        return eb;
 err:
-       for (; i > 0; i--)
+       for (; i > 0; i--) {
+               detach_extent_buffer_page(eb, eb->pages[i - 1]);
                __free_page(eb->pages[i - 1]);
+       }
        __free_extent_buffer(eb);
        return NULL;
 }
-- 
2.30.0

Reply via email to