|
@@ -5263,6 +5263,7 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
|
|
static void btrfs_end_bio(struct bio *bio, int err)
|
|
static void btrfs_end_bio(struct bio *bio, int err)
|
|
{
|
|
{
|
|
struct btrfs_bio *bbio = bio->bi_private;
|
|
struct btrfs_bio *bbio = bio->bi_private;
|
|
|
|
+ struct btrfs_device *dev = bbio->stripes[0].dev;
|
|
int is_orig_bio = 0;
|
|
int is_orig_bio = 0;
|
|
|
|
|
|
if (err) {
|
|
if (err) {
|
|
@@ -5270,7 +5271,6 @@ static void btrfs_end_bio(struct bio *bio, int err)
|
|
if (err == -EIO || err == -EREMOTEIO) {
|
|
if (err == -EIO || err == -EREMOTEIO) {
|
|
unsigned int stripe_index =
|
|
unsigned int stripe_index =
|
|
btrfs_io_bio(bio)->stripe_index;
|
|
btrfs_io_bio(bio)->stripe_index;
|
|
- struct btrfs_device *dev;
|
|
|
|
|
|
|
|
BUG_ON(stripe_index >= bbio->num_stripes);
|
|
BUG_ON(stripe_index >= bbio->num_stripes);
|
|
dev = bbio->stripes[stripe_index].dev;
|
|
dev = bbio->stripes[stripe_index].dev;
|
|
@@ -5292,6 +5292,8 @@ static void btrfs_end_bio(struct bio *bio, int err)
|
|
if (bio == bbio->orig_bio)
|
|
if (bio == bbio->orig_bio)
|
|
is_orig_bio = 1;
|
|
is_orig_bio = 1;
|
|
|
|
|
|
|
|
+ btrfs_bio_counter_dec(bbio->fs_info);
|
|
|
|
+
|
|
if (atomic_dec_and_test(&bbio->stripes_pending)) {
|
|
if (atomic_dec_and_test(&bbio->stripes_pending)) {
|
|
if (!is_orig_bio) {
|
|
if (!is_orig_bio) {
|
|
bio_put(bio);
|
|
bio_put(bio);
|
|
@@ -5440,6 +5442,9 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
bio->bi_bdev = dev->bdev;
|
|
bio->bi_bdev = dev->bdev;
|
|
|
|
+
|
|
|
|
+ btrfs_bio_counter_inc_noblocked(root->fs_info);
|
|
|
|
+
|
|
if (async)
|
|
if (async)
|
|
btrfs_schedule_bio(root, dev, rw, bio);
|
|
btrfs_schedule_bio(root, dev, rw, bio);
|
|
else
|
|
else
|
|
@@ -5508,28 +5513,38 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
|
|
length = bio->bi_size;
|
|
length = bio->bi_size;
|
|
map_length = length;
|
|
map_length = length;
|
|
|
|
|
|
|
|
+ btrfs_bio_counter_inc_blocked(root->fs_info);
|
|
ret = __btrfs_map_block(root->fs_info, rw, logical, &map_length, &bbio,
|
|
ret = __btrfs_map_block(root->fs_info, rw, logical, &map_length, &bbio,
|
|
mirror_num, &raid_map);
|
|
mirror_num, &raid_map);
|
|
- if (ret) /* -ENOMEM */
|
|
|
|
|
|
+ if (ret) {
|
|
|
|
+ btrfs_bio_counter_dec(root->fs_info);
|
|
return ret;
|
|
return ret;
|
|
|
|
+ }
|
|
|
|
|
|
total_devs = bbio->num_stripes;
|
|
total_devs = bbio->num_stripes;
|
|
bbio->orig_bio = first_bio;
|
|
bbio->orig_bio = first_bio;
|
|
bbio->private = first_bio->bi_private;
|
|
bbio->private = first_bio->bi_private;
|
|
bbio->end_io = first_bio->bi_end_io;
|
|
bbio->end_io = first_bio->bi_end_io;
|
|
|
|
+ bbio->fs_info = root->fs_info;
|
|
atomic_set(&bbio->stripes_pending, bbio->num_stripes);
|
|
atomic_set(&bbio->stripes_pending, bbio->num_stripes);
|
|
|
|
|
|
if (raid_map) {
|
|
if (raid_map) {
|
|
/* In this case, map_length has been set to the length of
|
|
/* In this case, map_length has been set to the length of
|
|
a single stripe; not the whole write */
|
|
a single stripe; not the whole write */
|
|
if (rw & WRITE) {
|
|
if (rw & WRITE) {
|
|
- return raid56_parity_write(root, bio, bbio,
|
|
|
|
- raid_map, map_length);
|
|
|
|
|
|
+ ret = raid56_parity_write(root, bio, bbio,
|
|
|
|
+ raid_map, map_length);
|
|
} else {
|
|
} else {
|
|
- return raid56_parity_recover(root, bio, bbio,
|
|
|
|
- raid_map, map_length,
|
|
|
|
- mirror_num);
|
|
|
|
|
|
+ ret = raid56_parity_recover(root, bio, bbio,
|
|
|
|
+ raid_map, map_length,
|
|
|
|
+ mirror_num);
|
|
}
|
|
}
|
|
|
|
+ /*
|
|
|
|
+ * FIXME, replace dosen't support raid56 yet, please fix
|
|
|
|
+ * it in the future.
|
|
|
|
+ */
|
|
|
|
+ btrfs_bio_counter_dec(root->fs_info);
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
if (map_length < length) {
|
|
if (map_length < length) {
|
|
@@ -5571,6 +5586,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
|
|
async_submit);
|
|
async_submit);
|
|
dev_nr++;
|
|
dev_nr++;
|
|
}
|
|
}
|
|
|
|
+ btrfs_bio_counter_dec(root->fs_info);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|