Commit a1d3c478 authored by Jan Schmidt's avatar Jan Schmidt

btrfs: btrfs_multi_bio replaced with btrfs_bio

btrfs_bio is a bio abstraction able to split and not complete after the last
bio has returned (like the old btrfs_multi_bio). Additionally, btrfs_bio
tracks the mirror_num used to read data which can be used for error
correction purposes.
Signed-off-by: default avatarJan Schmidt <list.btrfs@jan-o-sch.net>
parent d7728c96
...@@ -1770,18 +1770,18 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, ...@@ -1770,18 +1770,18 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
{ {
int ret; int ret;
u64 discarded_bytes = 0; u64 discarded_bytes = 0;
struct btrfs_multi_bio *multi = NULL; struct btrfs_bio *bbio = NULL;
/* Tell the block device(s) that the sectors can be discarded */ /* Tell the block device(s) that the sectors can be discarded */
ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD, ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD,
bytenr, &num_bytes, &multi, 0); bytenr, &num_bytes, &bbio, 0);
if (!ret) { if (!ret) {
struct btrfs_bio_stripe *stripe = multi->stripes; struct btrfs_bio_stripe *stripe = bbio->stripes;
int i; int i;
for (i = 0; i < multi->num_stripes; i++, stripe++) { for (i = 0; i < bbio->num_stripes; i++, stripe++) {
if (!stripe->dev->can_discard) if (!stripe->dev->can_discard)
continue; continue;
...@@ -1800,7 +1800,7 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, ...@@ -1800,7 +1800,7 @@ static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
*/ */
ret = 0; ret = 0;
} }
kfree(multi); kfree(bbio);
} }
if (actual_bytes) if (actual_bytes)
......
...@@ -572,7 +572,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) ...@@ -572,7 +572,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
struct scrub_dev *sdev = sbio->sdev; struct scrub_dev *sdev = sbio->sdev;
struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info; struct btrfs_fs_info *fs_info = sdev->dev->dev_root->fs_info;
struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree; struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
struct btrfs_multi_bio *multi = NULL; struct btrfs_bio *bbio = NULL;
struct scrub_fixup_nodatasum *fixup; struct scrub_fixup_nodatasum *fixup;
u64 logical = sbio->logical + ix * PAGE_SIZE; u64 logical = sbio->logical + ix * PAGE_SIZE;
u64 length; u64 length;
...@@ -610,8 +610,8 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) ...@@ -610,8 +610,8 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
length = PAGE_SIZE; length = PAGE_SIZE;
ret = btrfs_map_block(map_tree, REQ_WRITE, logical, &length, ret = btrfs_map_block(map_tree, REQ_WRITE, logical, &length,
&multi, 0); &bbio, 0);
if (ret || !multi || length < PAGE_SIZE) { if (ret || !bbio || length < PAGE_SIZE) {
printk(KERN_ERR printk(KERN_ERR
"scrub_fixup: btrfs_map_block failed us for %llu\n", "scrub_fixup: btrfs_map_block failed us for %llu\n",
(unsigned long long)logical); (unsigned long long)logical);
...@@ -619,19 +619,19 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) ...@@ -619,19 +619,19 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
return; return;
} }
if (multi->num_stripes == 1) if (bbio->num_stripes == 1)
/* there aren't any replicas */ /* there aren't any replicas */
goto uncorrectable; goto uncorrectable;
/* /*
* first find a good copy * first find a good copy
*/ */
for (i = 0; i < multi->num_stripes; ++i) { for (i = 0; i < bbio->num_stripes; ++i) {
if (i + 1 == sbio->spag[ix].mirror_num) if (i + 1 == sbio->spag[ix].mirror_num)
continue; continue;
if (scrub_fixup_io(READ, multi->stripes[i].dev->bdev, if (scrub_fixup_io(READ, bbio->stripes[i].dev->bdev,
multi->stripes[i].physical >> 9, bbio->stripes[i].physical >> 9,
sbio->bio->bi_io_vec[ix].bv_page)) { sbio->bio->bi_io_vec[ix].bv_page)) {
/* I/O-error, this is not a good copy */ /* I/O-error, this is not a good copy */
continue; continue;
...@@ -640,7 +640,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) ...@@ -640,7 +640,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
if (scrub_fixup_check(sbio, ix) == 0) if (scrub_fixup_check(sbio, ix) == 0)
break; break;
} }
if (i == multi->num_stripes) if (i == bbio->num_stripes)
goto uncorrectable; goto uncorrectable;
if (!sdev->readonly) { if (!sdev->readonly) {
...@@ -655,7 +655,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) ...@@ -655,7 +655,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
} }
} }
kfree(multi); kfree(bbio);
spin_lock(&sdev->stat_lock); spin_lock(&sdev->stat_lock);
++sdev->stat.corrected_errors; ++sdev->stat.corrected_errors;
spin_unlock(&sdev->stat_lock); spin_unlock(&sdev->stat_lock);
...@@ -665,7 +665,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix) ...@@ -665,7 +665,7 @@ static void scrub_fixup(struct scrub_bio *sbio, int ix)
return; return;
uncorrectable: uncorrectable:
kfree(multi); kfree(bbio);
spin_lock(&sdev->stat_lock); spin_lock(&sdev->stat_lock);
++sdev->stat.uncorrectable_errors; ++sdev->stat.uncorrectable_errors;
spin_unlock(&sdev->stat_lock); spin_unlock(&sdev->stat_lock);
......
...@@ -2848,7 +2848,7 @@ static int find_live_mirror(struct map_lookup *map, int first, int num, ...@@ -2848,7 +2848,7 @@ static int find_live_mirror(struct map_lookup *map, int first, int num,
static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_multi_bio **multi_ret, struct btrfs_bio **bbio_ret,
int mirror_num) int mirror_num)
{ {
struct extent_map *em; struct extent_map *em;
...@@ -2866,18 +2866,18 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -2866,18 +2866,18 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
int i; int i;
int num_stripes; int num_stripes;
int max_errors = 0; int max_errors = 0;
struct btrfs_multi_bio *multi = NULL; struct btrfs_bio *bbio = NULL;
if (multi_ret && !(rw & (REQ_WRITE | REQ_DISCARD))) if (bbio_ret && !(rw & (REQ_WRITE | REQ_DISCARD)))
stripes_allocated = 1; stripes_allocated = 1;
again: again:
if (multi_ret) { if (bbio_ret) {
multi = kzalloc(btrfs_multi_bio_size(stripes_allocated), bbio = kzalloc(btrfs_bio_size(stripes_allocated),
GFP_NOFS); GFP_NOFS);
if (!multi) if (!bbio)
return -ENOMEM; return -ENOMEM;
atomic_set(&multi->error, 0); atomic_set(&bbio->error, 0);
} }
read_lock(&em_tree->lock); read_lock(&em_tree->lock);
...@@ -2898,7 +2898,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -2898,7 +2898,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
if (mirror_num > map->num_stripes) if (mirror_num > map->num_stripes)
mirror_num = 0; mirror_num = 0;
/* if our multi bio struct is too small, back off and try again */ /* if our btrfs_bio struct is too small, back off and try again */
if (rw & REQ_WRITE) { if (rw & REQ_WRITE) {
if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_DUP)) { BTRFS_BLOCK_GROUP_DUP)) {
...@@ -2917,11 +2917,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -2917,11 +2917,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
stripes_required = map->num_stripes; stripes_required = map->num_stripes;
} }
} }
if (multi_ret && (rw & (REQ_WRITE | REQ_DISCARD)) && if (bbio_ret && (rw & (REQ_WRITE | REQ_DISCARD)) &&
stripes_allocated < stripes_required) { stripes_allocated < stripes_required) {
stripes_allocated = map->num_stripes; stripes_allocated = map->num_stripes;
free_extent_map(em); free_extent_map(em);
kfree(multi); kfree(bbio);
goto again; goto again;
} }
stripe_nr = offset; stripe_nr = offset;
...@@ -2950,7 +2950,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -2950,7 +2950,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
*length = em->len - offset; *length = em->len - offset;
} }
if (!multi_ret) if (!bbio_ret)
goto out; goto out;
num_stripes = 1; num_stripes = 1;
...@@ -2975,13 +2975,17 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -2975,13 +2975,17 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
stripe_index = find_live_mirror(map, 0, stripe_index = find_live_mirror(map, 0,
map->num_stripes, map->num_stripes,
current->pid % map->num_stripes); current->pid % map->num_stripes);
mirror_num = stripe_index + 1;
} }
} else if (map->type & BTRFS_BLOCK_GROUP_DUP) { } else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
if (rw & (REQ_WRITE | REQ_DISCARD)) if (rw & (REQ_WRITE | REQ_DISCARD)) {
num_stripes = map->num_stripes; num_stripes = map->num_stripes;
else if (mirror_num) } else if (mirror_num) {
stripe_index = mirror_num - 1; stripe_index = mirror_num - 1;
} else {
mirror_num = 1;
}
} else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
int factor = map->num_stripes / map->sub_stripes; int factor = map->num_stripes / map->sub_stripes;
...@@ -3001,6 +3005,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3001,6 +3005,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
stripe_index = find_live_mirror(map, stripe_index, stripe_index = find_live_mirror(map, stripe_index,
map->sub_stripes, stripe_index + map->sub_stripes, stripe_index +
current->pid % map->sub_stripes); current->pid % map->sub_stripes);
mirror_num = stripe_index + 1;
} }
} else { } else {
/* /*
...@@ -3009,15 +3014,16 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3009,15 +3014,16 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
* stripe_index is the number of our device in the stripe array * stripe_index is the number of our device in the stripe array
*/ */
stripe_index = do_div(stripe_nr, map->num_stripes); stripe_index = do_div(stripe_nr, map->num_stripes);
mirror_num = stripe_index + 1;
} }
BUG_ON(stripe_index >= map->num_stripes); BUG_ON(stripe_index >= map->num_stripes);
if (rw & REQ_DISCARD) { if (rw & REQ_DISCARD) {
for (i = 0; i < num_stripes; i++) { for (i = 0; i < num_stripes; i++) {
multi->stripes[i].physical = bbio->stripes[i].physical =
map->stripes[stripe_index].physical + map->stripes[stripe_index].physical +
stripe_offset + stripe_nr * map->stripe_len; stripe_offset + stripe_nr * map->stripe_len;
multi->stripes[i].dev = map->stripes[stripe_index].dev; bbio->stripes[i].dev = map->stripes[stripe_index].dev;
if (map->type & BTRFS_BLOCK_GROUP_RAID0) { if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
u64 stripes; u64 stripes;
...@@ -3038,16 +3044,16 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3038,16 +3044,16 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
} }
stripes = stripe_nr_end - 1 - j; stripes = stripe_nr_end - 1 - j;
do_div(stripes, map->num_stripes); do_div(stripes, map->num_stripes);
multi->stripes[i].length = map->stripe_len * bbio->stripes[i].length = map->stripe_len *
(stripes - stripe_nr + 1); (stripes - stripe_nr + 1);
if (i == 0) { if (i == 0) {
multi->stripes[i].length -= bbio->stripes[i].length -=
stripe_offset; stripe_offset;
stripe_offset = 0; stripe_offset = 0;
} }
if (stripe_index == last_stripe) if (stripe_index == last_stripe)
multi->stripes[i].length -= bbio->stripes[i].length -=
stripe_end_offset; stripe_end_offset;
} else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
u64 stripes; u64 stripes;
...@@ -3072,11 +3078,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3072,11 +3078,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
} }
stripes = stripe_nr_end - 1 - j; stripes = stripe_nr_end - 1 - j;
do_div(stripes, factor); do_div(stripes, factor);
multi->stripes[i].length = map->stripe_len * bbio->stripes[i].length = map->stripe_len *
(stripes - stripe_nr + 1); (stripes - stripe_nr + 1);
if (i < map->sub_stripes) { if (i < map->sub_stripes) {
multi->stripes[i].length -= bbio->stripes[i].length -=
stripe_offset; stripe_offset;
if (i == map->sub_stripes - 1) if (i == map->sub_stripes - 1)
stripe_offset = 0; stripe_offset = 0;
...@@ -3084,11 +3090,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3084,11 +3090,11 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
if (stripe_index >= last_stripe && if (stripe_index >= last_stripe &&
stripe_index <= (last_stripe + stripe_index <= (last_stripe +
map->sub_stripes - 1)) { map->sub_stripes - 1)) {
multi->stripes[i].length -= bbio->stripes[i].length -=
stripe_end_offset; stripe_end_offset;
} }
} else } else
multi->stripes[i].length = *length; bbio->stripes[i].length = *length;
stripe_index++; stripe_index++;
if (stripe_index == map->num_stripes) { if (stripe_index == map->num_stripes) {
...@@ -3099,19 +3105,20 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3099,19 +3105,20 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
} }
} else { } else {
for (i = 0; i < num_stripes; i++) { for (i = 0; i < num_stripes; i++) {
multi->stripes[i].physical = bbio->stripes[i].physical =
map->stripes[stripe_index].physical + map->stripes[stripe_index].physical +
stripe_offset + stripe_offset +
stripe_nr * map->stripe_len; stripe_nr * map->stripe_len;
multi->stripes[i].dev = bbio->stripes[i].dev =
map->stripes[stripe_index].dev; map->stripes[stripe_index].dev;
stripe_index++; stripe_index++;
} }
} }
if (multi_ret) { if (bbio_ret) {
*multi_ret = multi; *bbio_ret = bbio;
multi->num_stripes = num_stripes; bbio->num_stripes = num_stripes;
multi->max_errors = max_errors; bbio->max_errors = max_errors;
bbio->mirror_num = mirror_num;
} }
out: out:
free_extent_map(em); free_extent_map(em);
...@@ -3120,9 +3127,9 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, ...@@ -3120,9 +3127,9 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_multi_bio **multi_ret, int mirror_num) struct btrfs_bio **bbio_ret, int mirror_num)
{ {
return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, return __btrfs_map_block(map_tree, rw, logical, length, bbio_ret,
mirror_num); mirror_num);
} }
...@@ -3191,28 +3198,28 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, ...@@ -3191,28 +3198,28 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
return 0; return 0;
} }
static void end_bio_multi_stripe(struct bio *bio, int err) static void btrfs_end_bio(struct bio *bio, int err)
{ {
struct btrfs_multi_bio *multi = bio->bi_private; struct btrfs_bio *bbio = bio->bi_private;
int is_orig_bio = 0; int is_orig_bio = 0;
if (err) if (err)
atomic_inc(&multi->error); atomic_inc(&bbio->error);
if (bio == multi->orig_bio) if (bio == bbio->orig_bio)
is_orig_bio = 1; is_orig_bio = 1;
if (atomic_dec_and_test(&multi->stripes_pending)) { if (atomic_dec_and_test(&bbio->stripes_pending)) {
if (!is_orig_bio) { if (!is_orig_bio) {
bio_put(bio); bio_put(bio);
bio = multi->orig_bio; bio = bbio->orig_bio;
} }
bio->bi_private = multi->private; bio->bi_private = bbio->private;
bio->bi_end_io = multi->end_io; bio->bi_end_io = bbio->end_io;
/* only send an error to the higher layers if it is /* only send an error to the higher layers if it is
* beyond the tolerance of the multi-bio * beyond the tolerance of the multi-bio
*/ */
if (atomic_read(&multi->error) > multi->max_errors) { if (atomic_read(&bbio->error) > bbio->max_errors) {
err = -EIO; err = -EIO;
} else if (err) { } else if (err) {
/* /*
...@@ -3222,7 +3229,7 @@ static void end_bio_multi_stripe(struct bio *bio, int err) ...@@ -3222,7 +3229,7 @@ static void end_bio_multi_stripe(struct bio *bio, int err)
set_bit(BIO_UPTODATE, &bio->bi_flags); set_bit(BIO_UPTODATE, &bio->bi_flags);
err = 0; err = 0;
} }
kfree(multi); kfree(bbio);
bio_endio(bio, err); bio_endio(bio, err);
} else if (!is_orig_bio) { } else if (!is_orig_bio) {
...@@ -3302,20 +3309,20 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, ...@@ -3302,20 +3309,20 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
u64 logical = (u64)bio->bi_sector << 9; u64 logical = (u64)bio->bi_sector << 9;
u64 length = 0; u64 length = 0;
u64 map_length; u64 map_length;
struct btrfs_multi_bio *multi = NULL;
int ret; int ret;
int dev_nr = 0; int dev_nr = 0;
int total_devs = 1; int total_devs = 1;
struct btrfs_bio *bbio = NULL;
length = bio->bi_size; length = bio->bi_size;
map_tree = &root->fs_info->mapping_tree; map_tree = &root->fs_info->mapping_tree;
map_length = length; map_length = length;
ret = btrfs_map_block(map_tree, rw, logical, &map_length, &multi, ret = btrfs_map_block(map_tree, rw, logical, &map_length, &bbio,
mirror_num); mirror_num);
BUG_ON(ret); BUG_ON(ret);
total_devs = multi->num_stripes; total_devs = bbio->num_stripes;
if (map_length < length) { if (map_length < length) {
printk(KERN_CRIT "mapping failed logical %llu bio len %llu " printk(KERN_CRIT "mapping failed logical %llu bio len %llu "
"len %llu\n", (unsigned long long)logical, "len %llu\n", (unsigned long long)logical,
...@@ -3323,25 +3330,28 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, ...@@ -3323,25 +3330,28 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
(unsigned long long)map_length); (unsigned long long)map_length);
BUG(); BUG();
} }
multi->end_io = first_bio->bi_end_io;
multi->private = first_bio->bi_private; bbio->orig_bio = first_bio;
multi->orig_bio = first_bio; bbio->private = first_bio->bi_private;
atomic_set(&multi->stripes_pending, multi->num_stripes); bbio->end_io = first_bio->bi_end_io;
atomic_set(&bbio->stripes_pending, bbio->num_stripes);
while (dev_nr < total_devs) { while (dev_nr < total_devs) {
if (total_devs > 1) {
if (dev_nr < total_devs - 1) { if (dev_nr < total_devs - 1) {
bio = bio_clone(first_bio, GFP_NOFS); bio = bio_clone(first_bio, GFP_NOFS);
BUG_ON(!bio); BUG_ON(!bio);
} else { } else {
bio = first_bio; bio = first_bio;
} }
bio->bi_private = multi; bio->bi_private = bbio;
bio->bi_end_io = end_bio_multi_stripe; bio->bi_end_io = btrfs_end_bio;
} bio->bi_sector = bbio->stripes[dev_nr].physical >> 9;
bio->bi_sector = multi->stripes[dev_nr].physical >> 9; dev = bbio->stripes[dev_nr].dev;
dev = multi->stripes[dev_nr].dev;
if (dev && dev->bdev && (rw != WRITE || dev->writeable)) { if (dev && dev->bdev && (rw != WRITE || dev->writeable)) {
pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu "
"(%s id %llu), size=%u\n", rw,
(u64)bio->bi_sector, (u_long)dev->bdev->bd_dev,
dev->name, dev->devid, bio->bi_size);
bio->bi_bdev = dev->bdev; bio->bi_bdev = dev->bdev;
if (async_submit) if (async_submit)
schedule_bio(root, dev, rw, bio); schedule_bio(root, dev, rw, bio);
...@@ -3354,8 +3364,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, ...@@ -3354,8 +3364,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
} }
dev_nr++; dev_nr++;
} }
if (total_devs == 1)
kfree(multi);
return 0; return 0;
} }
......
...@@ -136,7 +136,10 @@ struct btrfs_bio_stripe { ...@@ -136,7 +136,10 @@ struct btrfs_bio_stripe {
u64 length; /* only used for discard mappings */ u64 length; /* only used for discard mappings */
}; };
struct btrfs_multi_bio { struct btrfs_bio;
typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
struct btrfs_bio {
atomic_t stripes_pending; atomic_t stripes_pending;
bio_end_io_t *end_io; bio_end_io_t *end_io;
struct bio *orig_bio; struct bio *orig_bio;
...@@ -144,6 +147,7 @@ struct btrfs_multi_bio { ...@@ -144,6 +147,7 @@ struct btrfs_multi_bio {
atomic_t error; atomic_t error;
int max_errors; int max_errors;
int num_stripes; int num_stripes;
int mirror_num;
struct btrfs_bio_stripe stripes[]; struct btrfs_bio_stripe stripes[];
}; };
...@@ -171,7 +175,7 @@ struct map_lookup { ...@@ -171,7 +175,7 @@ struct map_lookup {
int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
u64 end, u64 *length); u64 end, u64 *length);
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \ #define btrfs_bio_size(n) (sizeof(struct btrfs_bio) + \
(sizeof(struct btrfs_bio_stripe) * (n))) (sizeof(struct btrfs_bio_stripe) * (n)))
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
...@@ -180,7 +184,7 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, ...@@ -180,7 +184,7 @@ int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
u64 chunk_offset, u64 start, u64 num_bytes); u64 chunk_offset, u64 start, u64 num_bytes);
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
u64 logical, u64 *length, u64 logical, u64 *length,
struct btrfs_multi_bio **multi_ret, int mirror_num); struct btrfs_bio **bbio_ret, int mirror_num);
int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
u64 chunk_start, u64 physical, u64 devid, u64 chunk_start, u64 physical, u64 devid,
u64 **logical, int *naddrs, int *stripe_len); u64 **logical, int *naddrs, int *stripe_len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment