• Qu Wenruo's avatar
    btrfs: don't check stripe length if the profile is not stripe based · bf08387f
    Qu Wenruo authored
    [BUG]
    When debugging calc_bio_boundaries(), I found that even for RAID1
    metadata, we're following stripe length to calculate stripe boundary.
    
      # mkfs.btrfs -m raid1 -d raid1 /dev/test/scratch[12]
      # mount /dev/test/scratch /mnt/btrfs
      # xfs_io -f -c "pwrite 0 64K" /mnt/btrfs/file
      # umount
    
    Above very basic operations will make calc_bio_boundaries() to report
    the following result:
    
      submit_extent_page: r/i=1/1 file_offset=22036480 len_to_stripe_boundary=49152
      submit_extent_page: r/i=1/1 file_offset=30474240 len_to_stripe_boundary=65536
      ...
      submit_extent_page: r/i=1/1 file_offset=30523392 len_to_stripe_boundary=16384
      submit_extent_page: r/i=1/1 file_offset=30457856 len_to_stripe_boundary=16384
      submit_extent_page: r/i=5/257 file_offset=0 len_to_stripe_boundary=65536
      submit_extent_page: r/i=5/257 file_offset=65536 len_to_stripe_boundary=65536
      submit_extent_page: r/i=1/1 file_offset=30490624 len_to_stripe_boundary=49152
      submit_extent_page: r/i=1/1 file_offset=30507008 len_to_stripe_boundary=32768
    
    Where "r/i" is the rootid and inode, 1/1 means they metadata.
    The remaining names match the member used in kernel.
    
    Even all data/metadata are using RAID1, we're still following stripe
    length.
    
    [CAUSE]
    This behavior is caused by a wrong condition in btrfs_get_io_geometry():
    
    	if (map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
    		/* Fill using stripe_len */
    		len = min_t(u64, em->len - offset, max_len);
    	} else {
    		len = em->len - offset;
    	}
    
    This means, only for SINGLE we will not follow stripe_len.
    
    However for profiles like RAID1*, DUP, they don't need to bother
    stripe_len.
    
    This can lead to unnecessary bio split for RAID1*/DUP profiles, and can
    even be a blockage for future zoned RAID support.
    
    [FIX]
    Introduce one single-use macro, BTRFS_BLOCK_GROUP_STRIPE_MASK, and
    change the condition to only calculate the length using stripe length
    for stripe based profiles.
    Reviewed-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
    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>
    bf08387f
volumes.c 224 KB