• Qu Wenruo's avatar
    btrfs: scrub: fix subpage repair error caused by hard coded PAGE_SIZE · 8df507cb
    Qu Wenruo authored
    [BUG]
    For the following file layout, scrub will not be able to repair all
    these two repairable error, but in fact make one corruption even
    unrepairable:
    
    	  inode offset 0      4k     8K
    Mirror 1               |XXXXXX|      |
    Mirror 2               |      |XXXXXX|
    
    [CAUSE]
    The root cause is the hard coded PAGE_SIZE, which makes scrub repair to
    go crazy for subpage.
    
    For above case, when reading the first sector, we use PAGE_SIZE other
    than sectorsize to read, which makes us to read the full range [0, 64K).
    In fact, after 8K there may be no data at all, we can just get some
    garbage.
    
    Then when doing the repair, we also writeback a full page from mirror 2,
    this means, we will also writeback the corrupted data in mirror 2 back
    to mirror 1, leaving the range [4K, 8K) unrepairable.
    
    [FIX]
    This patch will modify the following PAGE_SIZE use with sectorsize:
    
    - scrub_print_warning_inode()
      Remove the min() and replace PAGE_SIZE with sectorsize.
      The min() makes no sense, as csum is done for the full sector with
      padding.
    
      This fixes a bug that subpage report extra length like:
       checksum error at logical 298844160 on dev /dev/mapper/arm_nvme-test,
       physical 575668224, root 5, inode 257, offset 0, length 12288, links 1 (path: file)
    
      Where the error is only 1 sector.
    
    - scrub_handle_errored_block()
      Comments with PAGE|page involved, all changed to sector.
    
    - scrub_setup_recheck_block()
    - scrub_repair_page_from_good_copy()
    - scrub_add_page_to_wr_bio()
    - scrub_wr_submit()
    - scrub_add_page_to_rd_bio()
    - scrub_block_complete()
      Replace PAGE_SIZE with sectorsize.
      This solves several problems where we read/write extra range for
      subpage case.
    
    RAID56 code is excluded intentionally, as RAID56 has extra PAGE_SIZE
    usage, and is not really safe enough.
    Thus we will reject RAID56 for subpage in later commit.
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    8df507cb
scrub.c 114 KB