• Benjamin Marzinski's avatar
    md/raid5: recheck if reshape has finished with device_lock held · 25b3a823
    Benjamin Marzinski authored
    When handling an IO request, MD checks if a reshape is currently
    happening, and if so, where the IO sector is in relation to the reshape
    progress. MD uses conf->reshape_progress for both of these tasks.  When
    the reshape finishes, conf->reshape_progress is set to MaxSector.  If
    this occurs after MD checks if the reshape is currently happening but
    before it calls ahead_of_reshape(), then ahead_of_reshape() will end up
    comparing the IO sector against MaxSector. During a backwards reshape,
    this will make MD think the IO sector is in the area not yet reshaped,
    causing it to use the previous configuration, and map the IO to the
    sector where that data was before the reshape.
    
    This bug can be triggered by running the lvm2
    lvconvert-raid-reshape-linear_to_raid6-single-type.sh test in a loop,
    although it's very hard to reproduce.
    
    Fix this by factoring the code that checks where the IO sector is in
    relation to the reshape out to a helper called get_reshape_loc(),
    which reads reshape_progress and reshape_safe while holding the
    device_lock, and then rechecks if the reshape has finished before
    calling ahead_of_reshape with the saved values.
    
    Also use the helper during the REQ_NOWAIT check to see if the location
    is inside of the reshape region.
    
    Fixes: fef9c61f ("md/raid5: change reshape-progress measurement to cope with reshaping backwards.")
    Signed-off-by: default avatarBenjamin Marzinski <bmarzins@redhat.com>
    Signed-off-by: default avatarSong Liu <song@kernel.org>
    Link: https://lore.kernel.org/r/20240702151802.1632010-1-bmarzins@redhat.com
    25b3a823
raid5.c 253 KB