diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-06-18 22:42:55 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-06-19 17:20:56 -0400 |
commit | 8408c716d7a4ddd5954ce33f53a7d3cd2876cf65 (patch) | |
tree | 870ecde1af3c547ed7e067a86d4fa93740581b0d /fs/btrfs/volumes.c | |
parent | c55f13964008bfea7c5bee268f28b699cbad7f00 (diff) |
Btrfs: fix wrong error handle when the device is missing or is not writeable
The original bio might be submitted, so we shoud increase bi_remaining to
account for it when we deal with the error that the device is missing or
is not writeable, or we would skip the endio handle.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 4ca3c92a54b3..c83b24251e53 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -5359,6 +5359,15 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | |||
5359 | return 0; | 5359 | return 0; |
5360 | } | 5360 | } |
5361 | 5361 | ||
5362 | static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int err) | ||
5363 | { | ||
5364 | if (likely(bbio->flags & BTRFS_BIO_ORIG_BIO_SUBMITTED)) | ||
5365 | bio_endio_nodec(bio, err); | ||
5366 | else | ||
5367 | bio_endio(bio, err); | ||
5368 | kfree(bbio); | ||
5369 | } | ||
5370 | |||
5362 | static void btrfs_end_bio(struct bio *bio, int err) | 5371 | static void btrfs_end_bio(struct bio *bio, int err) |
5363 | { | 5372 | { |
5364 | struct btrfs_bio *bbio = bio->bi_private; | 5373 | struct btrfs_bio *bbio = bio->bi_private; |
@@ -5416,11 +5425,7 @@ static void btrfs_end_bio(struct bio *bio, int err) | |||
5416 | err = 0; | 5425 | err = 0; |
5417 | } | 5426 | } |
5418 | 5427 | ||
5419 | if (likely(bbio->flags & BTRFS_BIO_ORIG_BIO_SUBMITTED)) | 5428 | btrfs_end_bbio(bbio, bio, err); |
5420 | bio_endio_nodec(bio, err); | ||
5421 | else | ||
5422 | bio_endio(bio, err); | ||
5423 | kfree(bbio); | ||
5424 | } else if (!is_orig_bio) { | 5429 | } else if (!is_orig_bio) { |
5425 | bio_put(bio); | 5430 | bio_put(bio); |
5426 | } | 5431 | } |
@@ -5583,12 +5588,15 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical) | |||
5583 | { | 5588 | { |
5584 | atomic_inc(&bbio->error); | 5589 | atomic_inc(&bbio->error); |
5585 | if (atomic_dec_and_test(&bbio->stripes_pending)) { | 5590 | if (atomic_dec_and_test(&bbio->stripes_pending)) { |
5591 | /* Shoud be the original bio. */ | ||
5592 | WARN_ON(bio != bbio->orig_bio); | ||
5593 | |||
5586 | bio->bi_private = bbio->private; | 5594 | bio->bi_private = bbio->private; |
5587 | bio->bi_end_io = bbio->end_io; | 5595 | bio->bi_end_io = bbio->end_io; |
5588 | btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; | 5596 | btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; |
5589 | bio->bi_iter.bi_sector = logical >> 9; | 5597 | bio->bi_iter.bi_sector = logical >> 9; |
5590 | kfree(bbio); | 5598 | |
5591 | bio_endio(bio, -EIO); | 5599 | btrfs_end_bbio(bbio, bio, -EIO); |
5592 | } | 5600 | } |
5593 | } | 5601 | } |
5594 | 5602 | ||