mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 07:12:09 +00:00
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: Jan Schmidt <list.btrfs@jan-o-sch.net>
This commit is contained in:
parent
d7728c960d
commit
a1d3c4786a
4 changed files with 90 additions and 78 deletions
|
@ -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,
|
||||
u64 logical, u64 *length,
|
||||
struct btrfs_multi_bio **multi_ret,
|
||||
struct btrfs_bio **bbio_ret,
|
||||
int mirror_num)
|
||||
{
|
||||
struct extent_map *em;
|
||||
|
@ -2866,18 +2866,18 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
|
|||
int i;
|
||||
int num_stripes;
|
||||
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;
|
||||
again:
|
||||
if (multi_ret) {
|
||||
multi = kzalloc(btrfs_multi_bio_size(stripes_allocated),
|
||||
if (bbio_ret) {
|
||||
bbio = kzalloc(btrfs_bio_size(stripes_allocated),
|
||||
GFP_NOFS);
|
||||
if (!multi)
|
||||
if (!bbio)
|
||||
return -ENOMEM;
|
||||
|
||||
atomic_set(&multi->error, 0);
|
||||
atomic_set(&bbio->error, 0);
|
||||
}
|
||||
|
||||
read_lock(&em_tree->lock);
|
||||
|
@ -2898,7 +2898,7 @@ again:
|
|||
if (mirror_num > map->num_stripes)
|
||||
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 (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
|
||||
BTRFS_BLOCK_GROUP_DUP)) {
|
||||
|
@ -2917,11 +2917,11 @@ again:
|
|||
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 = map->num_stripes;
|
||||
free_extent_map(em);
|
||||
kfree(multi);
|
||||
kfree(bbio);
|
||||
goto again;
|
||||
}
|
||||
stripe_nr = offset;
|
||||
|
@ -2950,7 +2950,7 @@ again:
|
|||
*length = em->len - offset;
|
||||
}
|
||||
|
||||
if (!multi_ret)
|
||||
if (!bbio_ret)
|
||||
goto out;
|
||||
|
||||
num_stripes = 1;
|
||||
|
@ -2975,13 +2975,17 @@ again:
|
|||
stripe_index = find_live_mirror(map, 0,
|
||||
map->num_stripes,
|
||||
current->pid % map->num_stripes);
|
||||
mirror_num = stripe_index + 1;
|
||||
}
|
||||
|
||||
} 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;
|
||||
else if (mirror_num)
|
||||
} else if (mirror_num) {
|
||||
stripe_index = mirror_num - 1;
|
||||
} else {
|
||||
mirror_num = 1;
|
||||
}
|
||||
|
||||
} else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
|
||||
int factor = map->num_stripes / map->sub_stripes;
|
||||
|
@ -3001,6 +3005,7 @@ again:
|
|||
stripe_index = find_live_mirror(map, stripe_index,
|
||||
map->sub_stripes, stripe_index +
|
||||
current->pid % map->sub_stripes);
|
||||
mirror_num = stripe_index + 1;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -3009,15 +3014,16 @@ again:
|
|||
* stripe_index is the number of our device in the stripe array
|
||||
*/
|
||||
stripe_index = do_div(stripe_nr, map->num_stripes);
|
||||
mirror_num = stripe_index + 1;
|
||||
}
|
||||
BUG_ON(stripe_index >= map->num_stripes);
|
||||
|
||||
if (rw & REQ_DISCARD) {
|
||||
for (i = 0; i < num_stripes; i++) {
|
||||
multi->stripes[i].physical =
|
||||
bbio->stripes[i].physical =
|
||||
map->stripes[stripe_index].physical +
|
||||
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) {
|
||||
u64 stripes;
|
||||
|
@ -3038,16 +3044,16 @@ again:
|
|||
}
|
||||
stripes = stripe_nr_end - 1 - j;
|
||||
do_div(stripes, map->num_stripes);
|
||||
multi->stripes[i].length = map->stripe_len *
|
||||
bbio->stripes[i].length = map->stripe_len *
|
||||
(stripes - stripe_nr + 1);
|
||||
|
||||
if (i == 0) {
|
||||
multi->stripes[i].length -=
|
||||
bbio->stripes[i].length -=
|
||||
stripe_offset;
|
||||
stripe_offset = 0;
|
||||
}
|
||||
if (stripe_index == last_stripe)
|
||||
multi->stripes[i].length -=
|
||||
bbio->stripes[i].length -=
|
||||
stripe_end_offset;
|
||||
} else if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
|
||||
u64 stripes;
|
||||
|
@ -3072,11 +3078,11 @@ again:
|
|||
}
|
||||
stripes = stripe_nr_end - 1 - j;
|
||||
do_div(stripes, factor);
|
||||
multi->stripes[i].length = map->stripe_len *
|
||||
bbio->stripes[i].length = map->stripe_len *
|
||||
(stripes - stripe_nr + 1);
|
||||
|
||||
if (i < map->sub_stripes) {
|
||||
multi->stripes[i].length -=
|
||||
bbio->stripes[i].length -=
|
||||
stripe_offset;
|
||||
if (i == map->sub_stripes - 1)
|
||||
stripe_offset = 0;
|
||||
|
@ -3084,11 +3090,11 @@ again:
|
|||
if (stripe_index >= last_stripe &&
|
||||
stripe_index <= (last_stripe +
|
||||
map->sub_stripes - 1)) {
|
||||
multi->stripes[i].length -=
|
||||
bbio->stripes[i].length -=
|
||||
stripe_end_offset;
|
||||
}
|
||||
} else
|
||||
multi->stripes[i].length = *length;
|
||||
bbio->stripes[i].length = *length;
|
||||
|
||||
stripe_index++;
|
||||
if (stripe_index == map->num_stripes) {
|
||||
|
@ -3099,19 +3105,20 @@ again:
|
|||
}
|
||||
} else {
|
||||
for (i = 0; i < num_stripes; i++) {
|
||||
multi->stripes[i].physical =
|
||||
bbio->stripes[i].physical =
|
||||
map->stripes[stripe_index].physical +
|
||||
stripe_offset +
|
||||
stripe_nr * map->stripe_len;
|
||||
multi->stripes[i].dev =
|
||||
bbio->stripes[i].dev =
|
||||
map->stripes[stripe_index].dev;
|
||||
stripe_index++;
|
||||
}
|
||||
}
|
||||
if (multi_ret) {
|
||||
*multi_ret = multi;
|
||||
multi->num_stripes = num_stripes;
|
||||
multi->max_errors = max_errors;
|
||||
if (bbio_ret) {
|
||||
*bbio_ret = bbio;
|
||||
bbio->num_stripes = num_stripes;
|
||||
bbio->max_errors = max_errors;
|
||||
bbio->mirror_num = mirror_num;
|
||||
}
|
||||
out:
|
||||
free_extent_map(em);
|
||||
|
@ -3120,9 +3127,9 @@ out:
|
|||
|
||||
int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3191,28 +3198,28 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
|
|||
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;
|
||||
|
||||
if (err)
|
||||
atomic_inc(&multi->error);
|
||||
atomic_inc(&bbio->error);
|
||||
|
||||
if (bio == multi->orig_bio)
|
||||
if (bio == bbio->orig_bio)
|
||||
is_orig_bio = 1;
|
||||
|
||||
if (atomic_dec_and_test(&multi->stripes_pending)) {
|
||||
if (atomic_dec_and_test(&bbio->stripes_pending)) {
|
||||
if (!is_orig_bio) {
|
||||
bio_put(bio);
|
||||
bio = multi->orig_bio;
|
||||
bio = bbio->orig_bio;
|
||||
}
|
||||
bio->bi_private = multi->private;
|
||||
bio->bi_end_io = multi->end_io;
|
||||
bio->bi_private = bbio->private;
|
||||
bio->bi_end_io = bbio->end_io;
|
||||
/* only send an error to the higher layers if it is
|
||||
* 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;
|
||||
} else if (err) {
|
||||
/*
|
||||
|
@ -3222,7 +3229,7 @@ static void end_bio_multi_stripe(struct bio *bio, int err)
|
|||
set_bit(BIO_UPTODATE, &bio->bi_flags);
|
||||
err = 0;
|
||||
}
|
||||
kfree(multi);
|
||||
kfree(bbio);
|
||||
|
||||
bio_endio(bio, err);
|
||||
} else if (!is_orig_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 length = 0;
|
||||
u64 map_length;
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
int ret;
|
||||
int dev_nr = 0;
|
||||
int total_devs = 1;
|
||||
struct btrfs_bio *bbio = NULL;
|
||||
|
||||
length = bio->bi_size;
|
||||
map_tree = &root->fs_info->mapping_tree;
|
||||
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);
|
||||
BUG_ON(ret);
|
||||
|
||||
total_devs = multi->num_stripes;
|
||||
total_devs = bbio->num_stripes;
|
||||
if (map_length < length) {
|
||||
printk(KERN_CRIT "mapping failed logical %llu bio len %llu "
|
||||
"len %llu\n", (unsigned long long)logical,
|
||||
|
@ -3323,25 +3330,28 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
|
|||
(unsigned long long)map_length);
|
||||
BUG();
|
||||
}
|
||||
multi->end_io = first_bio->bi_end_io;
|
||||
multi->private = first_bio->bi_private;
|
||||
multi->orig_bio = first_bio;
|
||||
atomic_set(&multi->stripes_pending, multi->num_stripes);
|
||||
|
||||
bbio->orig_bio = first_bio;
|
||||
bbio->private = first_bio->bi_private;
|
||||
bbio->end_io = first_bio->bi_end_io;
|
||||
atomic_set(&bbio->stripes_pending, bbio->num_stripes);
|
||||
|
||||
while (dev_nr < total_devs) {
|
||||
if (total_devs > 1) {
|
||||
if (dev_nr < total_devs - 1) {
|
||||
bio = bio_clone(first_bio, GFP_NOFS);
|
||||
BUG_ON(!bio);
|
||||
} else {
|
||||
bio = first_bio;
|
||||
}
|
||||
bio->bi_private = multi;
|
||||
bio->bi_end_io = end_bio_multi_stripe;
|
||||
if (dev_nr < total_devs - 1) {
|
||||
bio = bio_clone(first_bio, GFP_NOFS);
|
||||
BUG_ON(!bio);
|
||||
} else {
|
||||
bio = first_bio;
|
||||
}
|
||||
bio->bi_sector = multi->stripes[dev_nr].physical >> 9;
|
||||
dev = multi->stripes[dev_nr].dev;
|
||||
bio->bi_private = bbio;
|
||||
bio->bi_end_io = btrfs_end_bio;
|
||||
bio->bi_sector = bbio->stripes[dev_nr].physical >> 9;
|
||||
dev = bbio->stripes[dev_nr].dev;
|
||||
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;
|
||||
if (async_submit)
|
||||
schedule_bio(root, dev, rw, bio);
|
||||
|
@ -3354,8 +3364,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
|
|||
}
|
||||
dev_nr++;
|
||||
}
|
||||
if (total_devs == 1)
|
||||
kfree(multi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue