]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: re-introduce struct btrfs_io_geometry
authorJohannes Thumshirn <johannes.thumshirn@wdc.com>
Wed, 13 Dec 2023 14:42:57 +0000 (06:42 -0800)
committerDavid Sterba <dsterba@suse.com>
Fri, 15 Dec 2023 22:03:58 +0000 (23:03 +0100)
Re-introduce struct btrfs_io_geometry, holding the necessary bits and
pieces needed in btrfs_map_block() to decide the I/O geometry of a specific
block mapping.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index f23223f0ea5b14bfa23ca6a5409953ae45bd3e1d..e3f75ede9174620adcb0739b548327f952154df7 100644 (file)
                                         BTRFS_BLOCK_GROUP_RAID10 | \
                                         BTRFS_BLOCK_GROUP_RAID56_MASK)
 
+struct btrfs_io_geometry {
+       u32 stripe_index;
+       u32 stripe_nr;
+       int mirror_num;
+       int num_stripes;
+       u64 stripe_offset;
+       u64 raid56_full_stripe_start;
+       int max_errors;
+       enum btrfs_map_op op;
+};
+
 const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID10] = {
                .sub_stripes    = 2,
@@ -6392,28 +6403,27 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                    struct btrfs_io_stripe *smap, int *mirror_num_ret)
 {
        struct btrfs_chunk_map *map;
+       struct btrfs_io_geometry io_geom = { 0 };
        u64 map_offset;
-       u64 stripe_offset;
-       u32 stripe_nr;
-       u32 stripe_index;
        int data_stripes;
        int i;
        int ret = 0;
-       int mirror_num = (mirror_num_ret ? *mirror_num_ret : 0);
-       int num_stripes;
        int num_copies;
-       int max_errors = 0;
        struct btrfs_io_context *bioc = NULL;
        struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
        int dev_replace_is_ongoing = 0;
        u16 num_alloc_stripes;
-       u64 raid56_full_stripe_start = (u64)-1;
        u64 max_len;
 
        ASSERT(bioc_ret);
 
+       io_geom.mirror_num = (mirror_num_ret ? *mirror_num_ret : 0);
+       io_geom.num_stripes = 1;
+       io_geom.stripe_index = 0;
+       io_geom.op = op;
+
        num_copies = btrfs_num_copies(fs_info, logical, fs_info->sectorsize);
-       if (mirror_num > num_copies)
+       if (io_geom.mirror_num > num_copies)
                return -EINVAL;
 
        map = btrfs_get_chunk_map(fs_info, logical, *length);
@@ -6423,8 +6433,10 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        data_stripes = nr_data_stripes(map);
 
        map_offset = logical - map->start;
-       max_len = btrfs_max_io_len(map, op, map_offset, &stripe_nr,
-                                  &stripe_offset, &raid56_full_stripe_start);
+       io_geom.raid56_full_stripe_start = (u64)-1;
+       max_len = btrfs_max_io_len(map, io_geom.op, map_offset, &io_geom.stripe_nr,
+                                  &io_geom.stripe_offset,
+                                  &io_geom.raid56_full_stripe_start);
        *length = min_t(u64, map->chunk_len - map_offset, max_len);
 
        down_read(&dev_replace->rwsem);
@@ -6436,53 +6448,51 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        if (!dev_replace_is_ongoing)
                up_read(&dev_replace->rwsem);
 
-       num_stripes = 1;
-       stripe_index = 0;
        if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
-               stripe_index = stripe_nr % map->num_stripes;
-               stripe_nr /= map->num_stripes;
+               io_geom.stripe_index = io_geom.stripe_nr % map->num_stripes;
+               io_geom.stripe_nr /= map->num_stripes;
                if (op == BTRFS_MAP_READ)
-                       mirror_num = 1;
+                       io_geom.mirror_num = 1;
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID1_MASK) {
                if (op != BTRFS_MAP_READ) {
-                       num_stripes = map->num_stripes;
-               } else if (mirror_num) {
-                       stripe_index = mirror_num - 1;
+                       io_geom.num_stripes = map->num_stripes;
+               } else if (io_geom.mirror_num) {
+                       io_geom.stripe_index = io_geom.mirror_num - 1;
                } else {
-                       stripe_index = find_live_mirror(fs_info, map, 0,
+                       io_geom.stripe_index = find_live_mirror(fs_info, map, 0,
                                            dev_replace_is_ongoing);
-                       mirror_num = stripe_index + 1;
+                       io_geom.mirror_num = io_geom.stripe_index + 1;
                }
 
        } else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
                if (op != BTRFS_MAP_READ) {
-                       num_stripes = map->num_stripes;
-               } else if (mirror_num) {
-                       stripe_index = mirror_num - 1;
+                       io_geom.num_stripes = map->num_stripes;
+               } else if (io_geom.mirror_num) {
+                       io_geom.stripe_index = io_geom.mirror_num - 1;
                } else {
-                       mirror_num = 1;
+                       io_geom.mirror_num = 1;
                }
 
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
                u32 factor = map->num_stripes / map->sub_stripes;
 
-               stripe_index = (stripe_nr % factor) * map->sub_stripes;
-               stripe_nr /= factor;
+               io_geom.stripe_index = (io_geom.stripe_nr % factor) * map->sub_stripes;
+               io_geom.stripe_nr /= factor;
 
                if (op != BTRFS_MAP_READ)
-                       num_stripes = map->sub_stripes;
-               else if (mirror_num)
-                       stripe_index += mirror_num - 1;
+                       io_geom.num_stripes = map->sub_stripes;
+               else if (io_geom.mirror_num)
+                       io_geom.stripe_index += io_geom.mirror_num - 1;
                else {
-                       int old_stripe_index = stripe_index;
-                       stripe_index = find_live_mirror(fs_info, map,
-                                             stripe_index,
+                       int old_stripe_index = io_geom.stripe_index;
+                       io_geom.stripe_index = find_live_mirror(fs_info, map,
+                                             io_geom.stripe_index,
                                              dev_replace_is_ongoing);
-                       mirror_num = stripe_index - old_stripe_index + 1;
+                       io_geom.mirror_num = io_geom.stripe_index - old_stripe_index + 1;
                }
 
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
-               if (op != BTRFS_MAP_READ || mirror_num > 1) {
+               if (op != BTRFS_MAP_READ || io_geom.mirror_num > 1) {
                        /*
                         * Needs full stripe mapping.
                         *
@@ -6494,29 +6504,33 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                         * but that can be expensive.  Here we just divide
                         * @stripe_nr with @data_stripes.
                         */
-                       stripe_nr /= data_stripes;
+                       io_geom.stripe_nr /= data_stripes;
 
                        /* RAID[56] write or recovery. Return all stripes */
-                       num_stripes = map->num_stripes;
-                       max_errors = btrfs_chunk_max_errors(map);
+                       io_geom.num_stripes = map->num_stripes;
+                       io_geom.max_errors = btrfs_chunk_max_errors(map);
 
                        /* Return the length to the full stripe end */
                        *length = min(logical + *length,
-                                     raid56_full_stripe_start + map->start +
-                                     btrfs_stripe_nr_to_offset(data_stripes)) -
+                                     io_geom.raid56_full_stripe_start +
+                                             map->start +
+                                             btrfs_stripe_nr_to_offset(
+                                                     data_stripes)) -
                                  logical;
-                       stripe_index = 0;
-                       stripe_offset = 0;
+                       io_geom.stripe_index = 0;
+                       io_geom.stripe_offset = 0;
                } else {
-                       ASSERT(mirror_num <= 1);
+                       ASSERT(io_geom.mirror_num <= 1);
                        /* Just grab the data stripe directly. */
-                       stripe_index = stripe_nr % data_stripes;
-                       stripe_nr /= data_stripes;
+                       io_geom.stripe_index = io_geom.stripe_nr % data_stripes;
+                       io_geom.stripe_nr /= data_stripes;
 
                        /* We distribute the parity blocks across stripes */
-                       stripe_index = (stripe_nr + stripe_index) % map->num_stripes;
-                       if (op == BTRFS_MAP_READ && mirror_num < 1)
-                               mirror_num = 1;
+                       io_geom.stripe_index =
+                               (io_geom.stripe_nr + io_geom.stripe_index) %
+                                       map->num_stripes;
+                       if (op == BTRFS_MAP_READ && io_geom.mirror_num < 1)
+                               io_geom.mirror_num = 1;
                }
        } else {
                /*
@@ -6524,19 +6538,19 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                 * device we have to walk to find the data, and stripe_index is
                 * the number of our device in the stripe array
                 */
-               stripe_index = stripe_nr % map->num_stripes;
-               stripe_nr /= map->num_stripes;
-               mirror_num = stripe_index + 1;
+               io_geom.stripe_index = io_geom.stripe_nr % map->num_stripes;
+               io_geom.stripe_nr /= map->num_stripes;
+               io_geom.mirror_num = io_geom.stripe_index + 1;
        }
-       if (stripe_index >= map->num_stripes) {
+       if (io_geom.stripe_index >= map->num_stripes) {
                btrfs_crit(fs_info,
                           "stripe index math went horribly wrong, got stripe_index=%u, num_stripes=%u",
-                          stripe_index, map->num_stripes);
+                          io_geom.stripe_index, map->num_stripes);
                ret = -EINVAL;
                goto out;
        }
 
-       num_alloc_stripes = num_stripes;
+       num_alloc_stripes = io_geom.num_stripes;
        if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL &&
            op != BTRFS_MAP_READ)
                /*
@@ -6554,11 +6568,12 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
         * I/O context structure.
         */
        if (is_single_device_io(fs_info, smap, map, num_alloc_stripes, op,
-                               mirror_num)) {
+                               io_geom.mirror_num)) {
                ret = set_io_stripe(fs_info, op, logical, length, smap, map,
-                                   stripe_index, stripe_offset, stripe_nr);
+                                   io_geom.stripe_index, io_geom.stripe_offset,
+                                   io_geom.stripe_nr);
                if (mirror_num_ret)
-                       *mirror_num_ret = mirror_num;
+                       *mirror_num_ret = io_geom.mirror_num;
                *bioc_ret = NULL;
                goto out;
        }
@@ -6578,7 +6593,7 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
         * It's still mostly the same as other profiles, just with extra rotation.
         */
        if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK &&
-           (op != BTRFS_MAP_READ || mirror_num > 1)) {
+           (op != BTRFS_MAP_READ || io_geom.mirror_num > 1)) {
                /*
                 * For RAID56 @stripe_nr is already the number of full stripes
                 * before us, which is also the rotation value (needs to modulo
@@ -6588,12 +6603,13 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                 * modulo, to reduce one modulo call.
                 */
                bioc->full_stripe_logical = map->start +
-                       btrfs_stripe_nr_to_offset(stripe_nr * data_stripes);
-               for (int i = 0; i < num_stripes; i++) {
+                       btrfs_stripe_nr_to_offset(io_geom.stripe_nr * data_stripes);
+               for (int i = 0; i < io_geom.num_stripes; i++) {
                        ret = set_io_stripe(fs_info, op, logical, length,
                                            &bioc->stripes[i], map,
-                                           (i + stripe_nr) % num_stripes,
-                                           stripe_offset, stripe_nr);
+                                           (i + io_geom.stripe_nr) % io_geom.num_stripes,
+                                           io_geom.stripe_offset,
+                                           io_geom.stripe_nr);
                        if (ret < 0)
                                break;
                }
@@ -6602,13 +6618,15 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                 * For all other non-RAID56 profiles, just copy the target
                 * stripe into the bioc.
                 */
-               for (i = 0; i < num_stripes; i++) {
+               for (i = 0; i < io_geom.num_stripes; i++) {
                        ret = set_io_stripe(fs_info, op, logical, length,
-                                           &bioc->stripes[i], map, stripe_index,
-                                           stripe_offset, stripe_nr);
+                                           &bioc->stripes[i], map,
+                                           io_geom.stripe_index,
+                                           io_geom.stripe_offset,
+                                           io_geom.stripe_nr);
                        if (ret < 0)
                                break;
-                       stripe_index++;
+                       io_geom.stripe_index++;
                }
        }
 
@@ -6619,18 +6637,18 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
        }
 
        if (op != BTRFS_MAP_READ)
-               max_errors = btrfs_chunk_max_errors(map);
+               io_geom.max_errors = btrfs_chunk_max_errors(map);
 
        if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL &&
            op != BTRFS_MAP_READ) {
                handle_ops_on_dev_replace(op, bioc, dev_replace, logical,
-                                         &num_stripes, &max_errors);
+                                         &io_geom.num_stripes, &io_geom.max_errors);
        }
 
        *bioc_ret = bioc;
-       bioc->num_stripes = num_stripes;
-       bioc->max_errors = max_errors;
-       bioc->mirror_num = mirror_num;
+       bioc->num_stripes = io_geom.num_stripes;
+       bioc->max_errors = io_geom.max_errors;
+       bioc->mirror_num = io_geom.mirror_num;
 
 out:
        if (dev_replace_is_ongoing) {