diff options
-rw-r--r-- | fs/btrfs/extent_io.c | 46 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 6 |
2 files changed, 31 insertions, 21 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8df797432740..27fdb250b446 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2584,26 +2584,36 @@ static void end_bio_extent_readpage(struct bio *bio) | |||
2584 | 2584 | ||
2585 | if (tree->ops) { | 2585 | if (tree->ops) { |
2586 | ret = tree->ops->readpage_io_failed_hook(page, mirror); | 2586 | ret = tree->ops->readpage_io_failed_hook(page, mirror); |
2587 | if (!ret && !bio->bi_error) | 2587 | if (ret == -EAGAIN) { |
2588 | uptodate = 1; | 2588 | /* |
2589 | } else { | 2589 | * Data inode's readpage_io_failed_hook() always |
2590 | * returns -EAGAIN. | ||
2591 | * | ||
2592 | * The generic bio_readpage_error handles errors | ||
2593 | * the following way: If possible, new read | ||
2594 | * requests are created and submitted and will | ||
2595 | * end up in end_bio_extent_readpage as well (if | ||
2596 | * we're lucky, not in the !uptodate case). In | ||
2597 | * that case it returns 0 and we just go on with | ||
2598 | * the next page in our bio. If it can't handle | ||
2599 | * the error it will return -EIO and we remain | ||
2600 | * responsible for that page. | ||
2601 | */ | ||
2602 | ret = bio_readpage_error(bio, offset, page, | ||
2603 | start, end, mirror); | ||
2604 | if (ret == 0) { | ||
2605 | uptodate = !bio->bi_error; | ||
2606 | offset += len; | ||
2607 | continue; | ||
2608 | } | ||
2609 | } | ||
2610 | |||
2590 | /* | 2611 | /* |
2591 | * The generic bio_readpage_error handles errors the | 2612 | * metadata's readpage_io_failed_hook() always returns |
2592 | * following way: If possible, new read requests are | 2613 | * -EIO and fixes nothing. -EIO is also returned if |
2593 | * created and submitted and will end up in | 2614 | * data inode error could not be fixed. |
2594 | * end_bio_extent_readpage as well (if we're lucky, not | ||
2595 | * in the !uptodate case). In that case it returns 0 and | ||
2596 | * we just go on with the next page in our bio. If it | ||
2597 | * can't handle the error it will return -EIO and we | ||
2598 | * remain responsible for that page. | ||
2599 | */ | 2615 | */ |
2600 | ret = bio_readpage_error(bio, offset, page, start, end, | 2616 | ASSERT(ret == -EIO); |
2601 | mirror); | ||
2602 | if (ret == 0) { | ||
2603 | uptodate = !bio->bi_error; | ||
2604 | offset += len; | ||
2605 | continue; | ||
2606 | } | ||
2607 | } | 2617 | } |
2608 | readpage_ok: | 2618 | readpage_ok: |
2609 | if (likely(uptodate)) { | 2619 | if (likely(uptodate)) { |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e57191072aa3..876f1d36030c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -10523,9 +10523,9 @@ out_inode: | |||
10523 | } | 10523 | } |
10524 | 10524 | ||
10525 | __attribute__((const)) | 10525 | __attribute__((const)) |
10526 | static int dummy_readpage_io_failed_hook(struct page *page, int failed_mirror) | 10526 | static int btrfs_readpage_io_failed_hook(struct page *page, int failed_mirror) |
10527 | { | 10527 | { |
10528 | return 0; | 10528 | return -EAGAIN; |
10529 | } | 10529 | } |
10530 | 10530 | ||
10531 | static const struct inode_operations btrfs_dir_inode_operations = { | 10531 | static const struct inode_operations btrfs_dir_inode_operations = { |
@@ -10570,7 +10570,7 @@ static const struct extent_io_ops btrfs_extent_io_ops = { | |||
10570 | .submit_bio_hook = btrfs_submit_bio_hook, | 10570 | .submit_bio_hook = btrfs_submit_bio_hook, |
10571 | .readpage_end_io_hook = btrfs_readpage_end_io_hook, | 10571 | .readpage_end_io_hook = btrfs_readpage_end_io_hook, |
10572 | .merge_bio_hook = btrfs_merge_bio_hook, | 10572 | .merge_bio_hook = btrfs_merge_bio_hook, |
10573 | .readpage_io_failed_hook = dummy_readpage_io_failed_hook, | 10573 | .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, |
10574 | 10574 | ||
10575 | /* optional callbacks */ | 10575 | /* optional callbacks */ |
10576 | .fill_delalloc = run_delalloc_range, | 10576 | .fill_delalloc = run_delalloc_range, |