• Qu Wenruo's avatar
    btrfs: scrub: Don't append on-disk pages for raid56 scrub · 9a33944b
    Qu Wenruo authored
    In the following situation, scrub will calculate wrong parity to
    overwrite the correct one:
    
    RAID5 full stripe:
    
    Before
    |     Dev 1      |     Dev  2     |     Dev 3     |
    | Data stripe 1  | Data stripe 2  | Parity Stripe |
    --------------------------------------------------- 0
    | 0x0000 (Bad)   |     0xcdcd     |     0x0000    |
    --------------------------------------------------- 4K
    |     0xcdcd     |     0xcdcd     |     0x0000    |
    ...
    |     0xcdcd     |     0xcdcd     |     0x0000    |
    --------------------------------------------------- 64K
    
    After scrubbing dev3 only:
    
    |     Dev 1      |     Dev  2     |     Dev 3     |
    | Data stripe 1  | Data stripe 2  | Parity Stripe |
    --------------------------------------------------- 0
    | 0xcdcd (Good)  |     0xcdcd     | 0xcdcd (Bad)  |
    --------------------------------------------------- 4K
    |     0xcdcd     |     0xcdcd     |     0x0000    |
    ...
    |     0xcdcd     |     0xcdcd     |     0x0000    |
    --------------------------------------------------- 64K
    
    The reason is that after raid56 read rebuild rbio->stripe_pages are all
    correctly recovered (0xcd for data stripes).
    
    However when we check and repair parity in
    scrub_parity_check_and_repair(), we will append pages in sparity->spages
    list to rbio->bio_pages[], which contains old on-disk data.
    
    And when we submit parity data to disk, we calculate parity using
    rbio->bio_pages[] first, if rbio->bio_pages[] not found, then fallback
    to rbio->stripe_pages[].
    
    The patch fix it by not appending pages from sparity->spages.
    So finish_parity_scrub() will use rbio->stripe_pages[] which is correct.
    Signed-off-by: default avatarQu Wenruo <quwenruo@cn.fujitsu.com>
    Reviewed-by: default avatarLiu Bo <bo.li.liu@oracle.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    9a33944b
scrub.c 116 KB