btrfs: make set_btree_ioerr accept extent buffer and be subpage compatible
authorQu Wenruo <wqu@suse.com>
Thu, 25 Mar 2021 07:14:44 +0000 (15:14 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 19 Apr 2021 15:25:18 +0000 (17:25 +0200)
Current set_btree_ioerr() only accepts @page parameter and grabs extent
buffer from page::private.  This works fine for sector size == PAGE_SIZE
case, but not for subpage case.

Add an extra parameter, @eb, for callers to pass extent buffer to this
function, so that subpage code can reuse this function.

And also add subpage special handling to update
btrfs_subpage::error_bitmap.

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 b0fa996..18e69e1 100644 (file)
@@ -4012,12 +4012,11 @@ err_unlock:
        return ret;
 }
 
-static void set_btree_ioerr(struct page *page)
+static void set_btree_ioerr(struct page *page, struct extent_buffer *eb)
 {
-       struct extent_buffer *eb = (struct extent_buffer *)page->private;
-       struct btrfs_fs_info *fs_info;
+       struct btrfs_fs_info *fs_info = eb->fs_info;
 
-       SetPageError(page);
+       btrfs_page_set_error(fs_info, page, eb->start, eb->len);
        if (test_and_set_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags))
                return;
 
@@ -4025,7 +4024,6 @@ static void set_btree_ioerr(struct page *page)
         * If we error out, we should add back the dirty_metadata_bytes
         * to make it consistent.
         */
-       fs_info = eb->fs_info;
        percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
                                 eb->len, fs_info->dirty_metadata_batch);
 
@@ -4069,13 +4067,13 @@ static void set_btree_ioerr(struct page *page)
         */
        switch (eb->log_index) {
        case -1:
-               set_bit(BTRFS_FS_BTREE_ERR, &eb->fs_info->flags);
+               set_bit(BTRFS_FS_BTREE_ERR, &fs_info->flags);
                break;
        case 0:
-               set_bit(BTRFS_FS_LOG1_ERR, &eb->fs_info->flags);
+               set_bit(BTRFS_FS_LOG1_ERR, &fs_info->flags);
                break;
        case 1:
-               set_bit(BTRFS_FS_LOG2_ERR, &eb->fs_info->flags);
+               set_bit(BTRFS_FS_LOG2_ERR, &fs_info->flags);
                break;
        default:
                BUG(); /* unexpected, logic error */
@@ -4100,7 +4098,7 @@ static void end_bio_extent_buffer_writepage(struct bio *bio)
                if (bio->bi_status ||
                    test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) {
                        ClearPageUptodate(page);
-                       set_btree_ioerr(page);
+                       set_btree_ioerr(page, eb);
                }
 
                end_page_writeback(page);
@@ -4156,7 +4154,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
                                         end_bio_extent_buffer_writepage,
                                         0, 0, 0, false);
                if (ret) {
-                       set_btree_ioerr(p);
+                       set_btree_ioerr(p, eb);
                        if (PageWriteback(p))
                                end_page_writeback(p);
                        if (atomic_sub_and_test(num_pages - i, &eb->io_pages))