• Qu Wenruo's avatar
    btrfs: subpage: fix a crash in metadata repair path · 917ac778
    Qu Wenruo authored
    [BUG]
    Test case btrfs/027 would crash with subpage (64K page size, 4K
    sectorsize) with the following dying messages:
    
      debug: map_length=16384 length=65536 type=metadata|raid6(0x104)
      assertion failed: map_length >= length, in fs/btrfs/volumes.c:8093
      ------------[ cut here ]------------
      kernel BUG at fs/btrfs/messages.c:259!
      Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
      Call trace:
       btrfs_assertfail+0x28/0x2c [btrfs]
       btrfs_map_repair_block+0x150/0x2b8 [btrfs]
       btrfs_repair_io_failure+0xd4/0x31c [btrfs]
       btrfs_read_extent_buffer+0x150/0x16c [btrfs]
       read_tree_block+0x38/0xbc [btrfs]
       read_tree_root_path+0xfc/0x1bc [btrfs]
       btrfs_get_root_ref.part.0+0xd4/0x3a8 [btrfs]
       open_ctree+0xa30/0x172c [btrfs]
       btrfs_mount_root+0x3c4/0x4a4 [btrfs]
       legacy_get_tree+0x30/0x60
       vfs_get_tree+0x28/0xec
       vfs_kern_mount.part.0+0x90/0xd4
       vfs_kern_mount+0x14/0x28
       btrfs_mount+0x114/0x418 [btrfs]
       legacy_get_tree+0x30/0x60
       vfs_get_tree+0x28/0xec
       path_mount+0x3e0/0xb64
       __arm64_sys_mount+0x200/0x2d8
       invoke_syscall+0x48/0x114
       el0_svc_common.constprop.0+0x60/0x11c
       do_el0_svc+0x38/0x98
       el0_svc+0x40/0xa8
       el0t_64_sync_handler+0xf4/0x120
       el0t_64_sync+0x190/0x194
      Code: aa0403e2 b0fff060 91010000 959c2024 (d4210000)
    
    [CAUSE]
    In btrfs/027 we test RAID6 with missing devices, in this particular
    case, we're repairing a metadata at the end of a data stripe.
    
    But at btrfs_repair_io_failure(), we always pass a full PAGE for repair,
    and for subpage case this can cross stripe boundary and lead to the
    above BUG_ON().
    
    This metadata repair code is always there, since the introduction of
    subpage support, but this can trigger BUG_ON() after the bio split
    ability at btrfs_map_bio().
    
    [FIX]
    Instead of passing the old PAGE_SIZE, we calculate the correct length
    based on the eb size and page size for both regular and subpage cases.
    
    CC: stable@vger.kernel.org # 6.3+
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    917ac778
disk-io.c 146 KB