@@ -6772,29 +6772,15 @@ static void bioc_error(struct btrfs_io_context *bioc, struct bio *bio, u64 logic
}
}
-blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
- int mirror_num)
+static int submit_one_mapped_range(struct btrfs_fs_info *fs_info, struct bio *bio,
+ struct btrfs_io_context *bioc, u64 map_length,
+ int mirror_num)
{
- struct btrfs_device *dev;
struct bio *first_bio = bio;
- u64 logical = bio->bi_iter.bi_sector << 9;
- u64 length = 0;
- u64 map_length;
- int ret;
- int dev_nr;
+ u64 logical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
int total_devs;
- struct btrfs_io_context *bioc = NULL;
-
- length = bio->bi_iter.bi_size;
- map_length = length;
-
- btrfs_bio_counter_inc_blocked(fs_info);
- ret = __btrfs_map_block(fs_info, btrfs_op(bio), logical,
- &map_length, &bioc, mirror_num, 1);
- if (ret) {
- btrfs_bio_counter_dec(fs_info);
- return errno_to_blk_status(ret);
- }
+ int dev_nr;
+ int ret;
total_devs = bioc->num_stripes;
bioc->orig_bio = first_bio;
@@ -6813,18 +6799,19 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
mirror_num, 1);
}
- btrfs_bio_counter_dec(fs_info);
- return errno_to_blk_status(ret);
+ return ret;
}
- if (map_length < length) {
+ if (map_length < bio->bi_iter.bi_size) {
btrfs_crit(fs_info,
- "mapping failed logical %llu bio len %llu len %llu",
- logical, length, map_length);
+ "mapping failed logical %llu bio len %u len %llu",
+ logical, bio->bi_iter.bi_size, map_length);
BUG();
}
for (dev_nr = 0; dev_nr < total_devs; dev_nr++) {
+ struct btrfs_device *dev;
+
dev = bioc->stripes[dev_nr].dev;
if (!dev || !dev->bdev || test_bit(BTRFS_DEV_STATE_MISSING,
&dev->dev_state) ||
@@ -6841,6 +6828,34 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
submit_stripe_bio(bioc, bio, bioc->stripes[dev_nr].physical, dev);
}
+ return 0;
+}
+
+blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
+ int mirror_num)
+{
+ u64 logical = bio->bi_iter.bi_sector << 9;
+ u64 length = 0;
+ u64 map_length;
+ int ret;
+ struct btrfs_io_context *bioc = NULL;
+
+ length = bio->bi_iter.bi_size;
+ map_length = length;
+
+ btrfs_bio_counter_inc_blocked(fs_info);
+ ret = __btrfs_map_block(fs_info, btrfs_op(bio), logical,
+ &map_length, &bioc, mirror_num, 1);
+ if (ret) {
+ btrfs_bio_counter_dec(fs_info);
+ return errno_to_blk_status(ret);
+ }
+
+ ret = submit_one_mapped_range(fs_info, bio, bioc, map_length, mirror_num);
+ if (ret < 0) {
+ btrfs_bio_counter_dec(fs_info);
+ return errno_to_blk_status(ret);
+ }
btrfs_bio_counter_dec(fs_info);
return BLK_STS_OK;
}
Currently in btrfs_map_bio() we call __btrfs_map_block(), then using the returned bioc to submit real stripes. This is fine if we're only going to handle one bio a time. For the incoming bio split at btrfs_map_bio() time, we want to handle several differnet bios, thus there we introduce a new helper, submit_one_mapped_range() to handle the submission part, making it much easier to make it work in a loop. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/volumes.c | 65 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 25 deletions(-)