• Qu Wenruo's avatar
    btrfs: migrate btrfs_repair_io_failure() to folio interfaces · 96c36eaa
    Qu Wenruo authored
    [BUG]
    Test case btrfs/124 failed if larger metadata folio is enabled, the
    dying message looks like this:
    
     BTRFS error (device dm-2): bad tree block start, mirror 2 want 31686656 have 0
     BTRFS info (device dm-2): read error corrected: ino 0 off 31686656 (dev /dev/mapper/test-scratch2 sector 20928)
     BUG: kernel NULL pointer dereference, address: 0000000000000020
     #PF: supervisor read access in kernel mode
     #PF: error_code(0x0000) - not-present page
     CPU: 6 PID: 350881 Comm: btrfs Tainted: G           OE      6.7.0-rc3-custom+ #128
     Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS unknown 2/2/2022
     RIP: 0010:btrfs_read_extent_buffer+0x106/0x180 [btrfs]
     PKRU: 55555554
     Call Trace:
      <TASK>
      read_tree_block+0x33/0xb0 [btrfs]
      read_block_for_search+0x23e/0x340 [btrfs]
      btrfs_search_slot+0x2f9/0xe60 [btrfs]
      btrfs_lookup_csum+0x75/0x160 [btrfs]
      btrfs_lookup_bio_sums+0x21a/0x560 [btrfs]
      btrfs_submit_chunk+0x152/0x680 [btrfs]
      btrfs_submit_bio+0x1c/0x50 [btrfs]
      submit_one_bio+0x40/0x80 [btrfs]
      submit_extent_page+0x158/0x390 [btrfs]
      btrfs_do_readpage+0x330/0x740 [btrfs]
      extent_readahead+0x38d/0x6c0 [btrfs]
      read_pages+0x94/0x2c0
      page_cache_ra_unbounded+0x12d/0x190
      relocate_file_extent_cluster+0x7c1/0x9d0 [btrfs]
      relocate_block_group+0x2d3/0x560 [btrfs]
      btrfs_relocate_block_group+0x2c7/0x4b0 [btrfs]
      btrfs_relocate_chunk+0x4c/0x1a0 [btrfs]
      btrfs_balance+0x925/0x13c0 [btrfs]
      btrfs_ioctl+0x19f1/0x25d0 [btrfs]
      __x64_sys_ioctl+0x90/0xd0
      do_syscall_64+0x3f/0xf0
      entry_SYSCALL_64_after_hwframe+0x6e/0x76
    
    [CAUSE]
    The dying line is at btrfs_repair_io_failure() call inside
    btrfs_repair_eb_io_failure().
    
    The function is still relying on the extent buffer using page sized
    folios.
    When the extent buffer is using larger folio, we go into the 2nd slot of
    folios[], and triggered the NULL pointer dereference.
    
    [FIX]
    Migrate btrfs_repair_io_failure() to folio interfaces.
    
    So that when we hit a larger folio, we just submit the whole folio in
    one go.
    
    This also affects data repair path through btrfs_end_repair_bio(),
    thankfully data is still fully page based, we can just add an
    ASSERT(), and use page_folio() to convert the page to folio.
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    96c36eaa
disk-io.c 138 KB