diff options
author | Qu Wenruo <wqu@suse.com> | 2019-03-20 09:27:42 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2019-04-29 20:02:23 +0300 |
commit | 3065976b045f77a910809fa7699f99a1e7c0dbbb (patch) | |
tree | 23dd10206fd9f4ee11e97065bb545eaa592ae944 /fs/btrfs/extent_io.c | |
parent | f4340622e02261fae599e3da936ff4808b418173 (diff) | |
download | linux-3065976b045f77a910809fa7699f99a1e7c0dbbb.tar.xz |
btrfs: extent_io: Handle errors better in extent_write_full_page()
Since now flush_write_bio() could return error, kill the BUG_ON() first.
Then don't call flush_write_bio() unconditionally, instead we check the
return value from __extent_writepage() first.
If __extent_writepage() fails, we do cleanup, and return error without
submitting the possible corrupted or half-baked bio.
If __extent_writepage() successes, then we call flush_write_bio() and
return the result.
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 43091b29b8d7..9d52f3b78732 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -170,6 +170,16 @@ static int __must_check submit_one_bio(struct bio *bio, int mirror_num, return blk_status_to_errno(ret); } +/* Cleanup unsubmitted bios */ +static void end_write_bio(struct extent_page_data *epd, int ret) +{ + if (epd->bio) { + epd->bio->bi_status = errno_to_blk_status(ret); + bio_endio(epd->bio); + epd->bio = NULL; + } +} + /* * Submit bio from extent page data via submit_one_bio * @@ -3397,6 +3407,9 @@ done: * records are inserted to lock ranges in the tree, and as dirty areas * are found, they are marked writeback. Then the lock bits are removed * and the end_io handler clears the writeback ranges + * + * Return 0 if everything goes well. + * Return <0 for error. */ static int __extent_writepage(struct page *page, struct writeback_control *wbc, struct extent_page_data *epd) @@ -3466,6 +3479,7 @@ done: end_extent_writepage(page, ret, start, page_end); } unlock_page(page); + ASSERT(ret <= 0); return ret; done_unlocked: @@ -4007,7 +4021,6 @@ retry: int extent_write_full_page(struct page *page, struct writeback_control *wbc) { int ret; - int flush_ret; struct extent_page_data epd = { .bio = NULL, .tree = &BTRFS_I(page->mapping->host)->io_tree, @@ -4016,9 +4029,14 @@ int extent_write_full_page(struct page *page, struct writeback_control *wbc) }; ret = __extent_writepage(page, wbc, &epd); + ASSERT(ret <= 0); + if (ret < 0) { + end_write_bio(&epd, ret); + return ret; + } - flush_ret = flush_write_bio(&epd); - BUG_ON(flush_ret < 0); + ret = flush_write_bio(&epd); + ASSERT(ret <= 0); return ret; } |