• Qu Wenruo's avatar
    btrfs: dev-replace: properly follow its read mode · 7b31e045
    Qu Wenruo authored
    [BUG]
    Although dev replace ioctl has a way to specify the mode on whether we
    should read from the source device, it's not properly followed.
    
     # mkfs.btrfs -f -d raid1 -m raid1 $dev1 $dev2
     # mount $dev1 $mnt
     # xfs_io -f -c "pwrite 0 32M" $mnt/file
     # sync
     # btrfs replace start -r -f 1 $dev3 $mnt
    
    And one extra trace is added to scrub_submit(), showing the detail about
    the bio:
    
      btrfs-11569 [005] ...  37.0270: scrub_submit.part.0: devid=1 logical=22036480 phy=22036480 len=16384
      btrfs-11569 [005] ...  37.0273: scrub_submit.part.0: devid=1 logical=30457856 phy=30457856 len=32768
      btrfs-11569 [005] ...  37.0274: scrub_submit.part.0: devid=1 logical=30507008 phy=30507008 len=49152
      btrfs-11569 [005] ...  37.0274: scrub_submit.part.0: devid=1 logical=30605312 phy=30605312 len=32768
      btrfs-11569 [005] ...  37.0275: scrub_submit.part.0: devid=1 logical=30703616 phy=30703616 len=65536
      btrfs-11569 [005] ...  37.0281: scrub_submit.part.0: devid=1 logical=298844160 phy=298844160 len=131072
      ...
      btrfs-11569 [005] ...  37.0762: scrub_submit.part.0: devid=1 logical=322961408 phy=322961408 len=131072
      btrfs-11569 [005] ...  37.0762: scrub_submit.part.0: devid=1 logical=323092480 phy=323092480 len=131072
    
    One can see that all the reads are submitted to devid 1, even if we have
    specified "-r" option to avoid reading from the source device.
    
    [CAUSE]
    The dev-replace read mode is only set but not followed by scrub code at
    all.  In fact, only common read path is properly following the read
    mode, but scrub itself has its own read path, thus not following the
    mode.
    
    [FIX]
    Here we enhance scrub_find_good_copy() to also follow the read mode.
    
    The idea is pretty simple, in the first loop, we avoid the following
    devices:
    
    - Missing devices
      This is the existing condition
    
    - The source device if the replace wants to avoid it.
    
    And if above loop found no candidate (e.g. replace a single device),
    then we discard the 2nd condition, and try again.
    
    Since we're here, also enhance the function scrub_find_good_copy() by:
    
    - Remove the forward declaration
    
    - Makes it return int
      To indicates errors, e.g. no good mirror found.
    
    - Add extra error messages
    
    Now with the same trace, "btrfs replace start -r" works as expected:
    
      btrfs-1213 [000] ...  991.9059: scrub_submit.part.0: devid=2 logical=22036480 phy=1064960 len=16384
      btrfs-1213 [000] ...  991.9062: scrub_submit.part.0: devid=2 logical=30457856 phy=9486336 len=32768
      btrfs-1213 [000] ...  991.9063: scrub_submit.part.0: devid=2 logical=30507008 phy=9535488 len=49152
      btrfs-1213 [000] ...  991.9064: scrub_submit.part.0: devid=2 logical=30605312 phy=9633792 len=32768
      btrfs-1213 [000] ...  991.9065: scrub_submit.part.0: devid=2 logical=30703616 phy=9732096 len=65536
      btrfs-1213 [000] ...  991.9073: scrub_submit.part.0: devid=2 logical=298844160 phy=277872640 len=131072
      btrfs-1213 [000] ...  991.9075: scrub_submit.part.0: devid=2 logical=298975232 phy=278003712 len=131072
      btrfs-1213 [000] ...  991.9078: scrub_submit.part.0: devid=2 logical=299106304 phy=278134784 len=131072
      ...
      btrfs-1213 [000] ...  991.9474: scrub_submit.part.0: devid=2 logical=318504960 phy=297533440 len=131072
      btrfs-1213 [000] ...  991.9476: scrub_submit.part.0: devid=2 logical=318636032 phy=297664512 len=131072
      btrfs-1213 [000] ...  991.9479: scrub_submit.part.0: devid=2 logical=318767104 phy=297795584 len=131072
    Reviewed-by: default avatarAnand Jain <anand.jain@oracle.com>
    Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    7b31e045
scrub.c 128 KB