diff options
-rw-r--r-- | fs/btrfs/disk-io.c | 37 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 2 |
2 files changed, 38 insertions, 1 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index fd28c40e9ec3..2151828aa142 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -609,11 +609,47 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
609 | end = min_t(u64, eb->len, PAGE_CACHE_SIZE); | 609 | end = min_t(u64, eb->len, PAGE_CACHE_SIZE); |
610 | end = eb->start + end - 1; | 610 | end = eb->start + end - 1; |
611 | err: | 611 | err: |
612 | if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) { | ||
613 | clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags); | ||
614 | btree_readahead_hook(root, eb, eb->start, ret); | ||
615 | } | ||
616 | |||
612 | free_extent_buffer(eb); | 617 | free_extent_buffer(eb); |
613 | out: | 618 | out: |
614 | return ret; | 619 | return ret; |
615 | } | 620 | } |
616 | 621 | ||
622 | static int btree_io_failed_hook(struct bio *failed_bio, | ||
623 | struct page *page, u64 start, u64 end, | ||
624 | struct extent_state *state) | ||
625 | { | ||
626 | struct extent_io_tree *tree; | ||
627 | unsigned long len; | ||
628 | struct extent_buffer *eb; | ||
629 | struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; | ||
630 | |||
631 | tree = &BTRFS_I(page->mapping->host)->io_tree; | ||
632 | if (page->private == EXTENT_PAGE_PRIVATE) | ||
633 | goto out; | ||
634 | if (!page->private) | ||
635 | goto out; | ||
636 | |||
637 | len = page->private >> 2; | ||
638 | WARN_ON(len == 0); | ||
639 | |||
640 | eb = alloc_extent_buffer(tree, start, len, page); | ||
641 | if (eb == NULL) | ||
642 | goto out; | ||
643 | |||
644 | if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) { | ||
645 | clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags); | ||
646 | btree_readahead_hook(root, eb, eb->start, -EIO); | ||
647 | } | ||
648 | |||
649 | out: | ||
650 | return -EIO; /* we fixed nothing */ | ||
651 | } | ||
652 | |||
617 | static void end_workqueue_bio(struct bio *bio, int err) | 653 | static void end_workqueue_bio(struct bio *bio, int err) |
618 | { | 654 | { |
619 | struct end_io_wq *end_io_wq = bio->bi_private; | 655 | struct end_io_wq *end_io_wq = bio->bi_private; |
@@ -3166,6 +3202,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3166 | static struct extent_io_ops btree_extent_io_ops = { | 3202 | static struct extent_io_ops btree_extent_io_ops = { |
3167 | .write_cache_pages_lock_hook = btree_lock_page_hook, | 3203 | .write_cache_pages_lock_hook = btree_lock_page_hook, |
3168 | .readpage_end_io_hook = btree_readpage_end_io_hook, | 3204 | .readpage_end_io_hook = btree_readpage_end_io_hook, |
3205 | .readpage_io_failed_hook = btree_io_failed_hook, | ||
3169 | .submit_bio_hook = btree_submit_bio_hook, | 3206 | .submit_bio_hook = btree_submit_bio_hook, |
3170 | /* note we're sharing with inode.c for the merge bio hook */ | 3207 | /* note we're sharing with inode.c for the merge bio hook */ |
3171 | .merge_bio_hook = btrfs_merge_bio_hook, | 3208 | .merge_bio_hook = btrfs_merge_bio_hook, |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 823028e73cf8..deba714236d7 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -1731,7 +1731,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
1731 | if (!uptodate && tree->ops && | 1731 | if (!uptodate && tree->ops && |
1732 | tree->ops->readpage_io_failed_hook) { | 1732 | tree->ops->readpage_io_failed_hook) { |
1733 | ret = tree->ops->readpage_io_failed_hook(bio, page, | 1733 | ret = tree->ops->readpage_io_failed_hook(bio, page, |
1734 | start, end, NULL); | 1734 | start, end, state); |
1735 | if (ret == 0) { | 1735 | if (ret == 0) { |
1736 | uptodate = | 1736 | uptodate = |
1737 | test_bit(BIO_UPTODATE, &bio->bi_flags); | 1737 | test_bit(BIO_UPTODATE, &bio->bi_flags); |