@@ -6435,6 +6435,55 @@ static void map_blocks_raid10(struct btrfs_fs_info *fs_info,
64356435 io_geom -> mirror_num = io_geom -> stripe_index - old_stripe_index + 1 ;
64366436}
64376437
6438+ static void map_blocks_raid56_write (struct btrfs_chunk_map * map ,
6439+ struct btrfs_io_geometry * io_geom ,
6440+ u64 logical , u64 * length )
6441+ {
6442+ int data_stripes = nr_data_stripes (map );
6443+
6444+ /*
6445+ * Needs full stripe mapping.
6446+ *
6447+ * Push stripe_nr back to the start of the full stripe For those cases
6448+ * needing a full stripe, @stripe_nr is the full stripe number.
6449+ *
6450+ * Originally we go raid56_full_stripe_start / full_stripe_len, but
6451+ * that can be expensive. Here we just divide @stripe_nr with
6452+ * @data_stripes.
6453+ */
6454+ io_geom -> stripe_nr /= data_stripes ;
6455+
6456+ /* RAID[56] write or recovery. Return all stripes */
6457+ io_geom -> num_stripes = map -> num_stripes ;
6458+ io_geom -> max_errors = btrfs_chunk_max_errors (map );
6459+
6460+ /* Return the length to the full stripe end. */
6461+ * length = min (logical + * length ,
6462+ io_geom -> raid56_full_stripe_start + map -> start +
6463+ btrfs_stripe_nr_to_offset (data_stripes )) -
6464+ logical ;
6465+ io_geom -> stripe_index = 0 ;
6466+ io_geom -> stripe_offset = 0 ;
6467+ }
6468+
6469+ static void map_blocks_raid56_read (struct btrfs_chunk_map * map ,
6470+ struct btrfs_io_geometry * io_geom )
6471+ {
6472+ int data_stripes = nr_data_stripes (map );
6473+
6474+ ASSERT (io_geom -> mirror_num <= 1 );
6475+ /* Just grab the data stripe directly. */
6476+ io_geom -> stripe_index = io_geom -> stripe_nr % data_stripes ;
6477+ io_geom -> stripe_nr /= data_stripes ;
6478+
6479+ /* We distribute the parity blocks across stripes. */
6480+ io_geom -> stripe_index =
6481+ (io_geom -> stripe_nr + io_geom -> stripe_index ) % map -> num_stripes ;
6482+
6483+ if (io_geom -> op == BTRFS_MAP_READ && io_geom -> mirror_num < 1 )
6484+ io_geom -> mirror_num = 1 ;
6485+ }
6486+
64386487/*
64396488 * Map one logical range to one or more physical ranges.
64406489 *
@@ -6527,48 +6576,10 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
65276576 } else if (map -> type & BTRFS_BLOCK_GROUP_RAID10 ) {
65286577 map_blocks_raid10 (fs_info , map , & io_geom , dev_replace_is_ongoing );
65296578 } else if (map -> type & BTRFS_BLOCK_GROUP_RAID56_MASK ) {
6530- int data_stripes = nr_data_stripes (map );
6531-
6532- if (op != BTRFS_MAP_READ || io_geom .mirror_num > 1 ) {
6533- /*
6534- * Needs full stripe mapping.
6535- *
6536- * Push stripe_nr back to the start of the full stripe
6537- * For those cases needing a full stripe, @stripe_nr
6538- * is the full stripe number.
6539- *
6540- * Originally we go raid56_full_stripe_start / full_stripe_len,
6541- * but that can be expensive. Here we just divide
6542- * @stripe_nr with @data_stripes.
6543- */
6544- io_geom .stripe_nr /= data_stripes ;
6545-
6546- /* RAID[56] write or recovery. Return all stripes */
6547- io_geom .num_stripes = map -> num_stripes ;
6548- io_geom .max_errors = btrfs_chunk_max_errors (map );
6549-
6550- /* Return the length to the full stripe end */
6551- * length = min (logical + * length ,
6552- io_geom .raid56_full_stripe_start +
6553- map -> start +
6554- btrfs_stripe_nr_to_offset (
6555- data_stripes )) -
6556- logical ;
6557- io_geom .stripe_index = 0 ;
6558- io_geom .stripe_offset = 0 ;
6559- } else {
6560- ASSERT (io_geom .mirror_num <= 1 );
6561- /* Just grab the data stripe directly. */
6562- io_geom .stripe_index = io_geom .stripe_nr % data_stripes ;
6563- io_geom .stripe_nr /= data_stripes ;
6564-
6565- /* We distribute the parity blocks across stripes */
6566- io_geom .stripe_index =
6567- (io_geom .stripe_nr + io_geom .stripe_index ) %
6568- map -> num_stripes ;
6569- if (op == BTRFS_MAP_READ && io_geom .mirror_num < 1 )
6570- io_geom .mirror_num = 1 ;
6571- }
6579+ if (op != BTRFS_MAP_READ || io_geom .mirror_num > 1 )
6580+ map_blocks_raid56_write (map , & io_geom , logical , length );
6581+ else
6582+ map_blocks_raid56_read (map , & io_geom );
65726583 } else {
65736584 /*
65746585 * After this, stripe_nr is the number of stripes on this
0 commit comments