aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c43
1 files changed, 29 insertions, 14 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 53c5ea702799..6107b6958413 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -360,9 +360,11 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
360 u64 start, u64 parent_transid) 360 u64 start, u64 parent_transid)
361{ 361{
362 struct extent_io_tree *io_tree; 362 struct extent_io_tree *io_tree;
363 int failed = 0;
363 int ret; 364 int ret;
364 int num_copies = 0; 365 int num_copies = 0;
365 int mirror_num = 0; 366 int mirror_num = 0;
367 int failed_mirror = 0;
366 368
367 clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); 369 clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
368 io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; 370 io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree;
@@ -371,7 +373,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
371 WAIT_COMPLETE, 373 WAIT_COMPLETE,
372 btree_get_extent, mirror_num); 374 btree_get_extent, mirror_num);
373 if (!ret && !verify_parent_transid(io_tree, eb, parent_transid)) 375 if (!ret && !verify_parent_transid(io_tree, eb, parent_transid))
374 return ret; 376 break;
375 377
376 /* 378 /*
377 * This buffer's crc is fine, but its contents are corrupted, so 379 * This buffer's crc is fine, but its contents are corrupted, so
@@ -379,18 +381,31 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
379 * any less wrong. 381 * any less wrong.
380 */ 382 */
381 if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) 383 if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags))
382 return ret; 384 break;
385
386 if (!failed_mirror) {
387 failed = 1;
388 printk(KERN_ERR "failed mirror was %d\n", eb->failed_mirror);
389 failed_mirror = eb->failed_mirror;
390 }
383 391
384 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, 392 num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
385 eb->start, eb->len); 393 eb->start, eb->len);
386 if (num_copies == 1) 394 if (num_copies == 1)
387 return ret; 395 break;
388 396
389 mirror_num++; 397 mirror_num++;
398 if (mirror_num == failed_mirror)
399 mirror_num++;
400
390 if (mirror_num > num_copies) 401 if (mirror_num > num_copies)
391 return ret; 402 break;
392 } 403 }
393 return -EIO; 404
405 if (failed && !ret)
406 repair_eb_io_failure(root, eb, failed_mirror);
407
408 return ret;
394} 409}
395 410
396/* 411/*
@@ -575,6 +590,11 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
575 if (!reads_done) 590 if (!reads_done)
576 goto err; 591 goto err;
577 592
593 if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) {
594 ret = -EIO;
595 goto err;
596 }
597
578 found_start = btrfs_header_bytenr(eb); 598 found_start = btrfs_header_bytenr(eb);
579 if (found_start != eb->start) { 599 if (found_start != eb->start) {
580 printk_ratelimited(KERN_INFO "btrfs bad tree block start " 600 printk_ratelimited(KERN_INFO "btrfs bad tree block start "
@@ -626,21 +646,16 @@ out:
626 return ret; 646 return ret;
627} 647}
628 648
629static int btree_io_failed_hook(struct bio *failed_bio, 649static int btree_io_failed_hook(struct page *page, int failed_mirror)
630 struct page *page, u64 start, u64 end,
631 int mirror_num, struct extent_state *state)
632{ 650{
633 struct extent_buffer *eb; 651 struct extent_buffer *eb;
634 struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; 652 struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
635 653
636 eb = (struct extent_buffer *)page->private; 654 eb = (struct extent_buffer *)page->private;
637 if (page != eb->pages[0]) 655 set_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
638 return -EIO; 656 eb->failed_mirror = failed_mirror;
639 657 if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
640 if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
641 clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
642 btree_readahead_hook(root, eb, eb->start, -EIO); 658 btree_readahead_hook(root, eb, eb->start, -EIO);
643 }
644 return -EIO; /* we fixed nothing */ 659 return -EIO; /* we fixed nothing */
645} 660}
646 661