aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2012-03-26 21:57:36 -0400
committerChris Mason <chris.mason@oracle.com>2012-03-26 21:57:36 -0400
commitea466794084f55d8fcc100711cf17923bf57e962 (patch)
tree9905d556655ff0f036936ea51f9aa214bd2cbce8 /fs/btrfs/disk-io.c
parentf3f266ab1bfe4770375d24fa8e72a03278e9450a (diff)
Btrfs: deal with read errors on extent buffers differently
Since we need to read and write extent buffers in their entirety we can't use the normal bio_readpage_error stuff since it only works on a per page basis. So instead make it so that if we see an io error in endio we just mark the eb as having an IO error and then in btree_read_extent_buffer_pages we will manually try other mirrors and then overwrite the bad mirror if we find a good copy. This works with larger than page size blocks. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
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