aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/disk-io.c37
-rw-r--r--fs/btrfs/extent_io.c2
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;
611err: 611err:
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);
613out: 618out:
614 return ret; 619 return ret;
615} 620}
616 621
622static 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
649out:
650 return -EIO; /* we fixed nothing */
651}
652
617static void end_workqueue_bio(struct bio *bio, int err) 653static 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)
3166static struct extent_io_ops btree_extent_io_ops = { 3202static 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);