aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c66
1 files changed, 41 insertions, 25 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a492fd238c8..08760ff9bab 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -430,9 +430,9 @@ struct io_failure_record {
430 int last_mirror; 430 int last_mirror;
431}; 431};
432 432
433int btrfs_readpage_io_failed_hook(struct bio *failed_bio, 433int btrfs_io_failed_hook(struct bio *failed_bio,
434 struct page *page, u64 start, u64 end, 434 struct page *page, u64 start, u64 end,
435 struct extent_state *state) 435 struct extent_state *state)
436{ 436{
437 struct io_failure_record *failrec = NULL; 437 struct io_failure_record *failrec = NULL;
438 u64 private; 438 u64 private;
@@ -443,6 +443,7 @@ int btrfs_readpage_io_failed_hook(struct bio *failed_bio,
443 struct bio *bio; 443 struct bio *bio;
444 int num_copies; 444 int num_copies;
445 int ret; 445 int ret;
446 int rw;
446 u64 logical; 447 u64 logical;
447 448
448 ret = get_state_private(failure_tree, start, &private); 449 ret = get_state_private(failure_tree, start, &private);
@@ -505,7 +506,41 @@ int btrfs_readpage_io_failed_hook(struct bio *failed_bio,
505 bio->bi_bdev = failed_bio->bi_bdev; 506 bio->bi_bdev = failed_bio->bi_bdev;
506 bio->bi_size = 0; 507 bio->bi_size = 0;
507 bio_add_page(bio, page, failrec->len, start - page_offset(page)); 508 bio_add_page(bio, page, failrec->len, start - page_offset(page));
508 btrfs_submit_bio_hook(inode, READ, bio, failrec->last_mirror); 509 if (failed_bio->bi_rw & (1 << BIO_RW))
510 rw = WRITE;
511 else
512 rw = READ;
513
514 BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio,
515 failrec->last_mirror);
516 return 0;
517}
518
519int btrfs_clean_io_failures(struct inode *inode, u64 start)
520{
521 u64 private;
522 u64 private_failure;
523 struct io_failure_record *failure;
524 int ret;
525
526 private = 0;
527 if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private,
528 (u64)-1, 1, EXTENT_DIRTY)) {
529 ret = get_state_private(&BTRFS_I(inode)->io_failure_tree,
530 start, &private_failure);
531 if (ret == 0) {
532 failure = (struct io_failure_record *)(unsigned long)
533 private_failure;
534 set_state_private(&BTRFS_I(inode)->io_failure_tree,
535 failure->start, 0);
536 clear_extent_bits(&BTRFS_I(inode)->io_failure_tree,
537 failure->start,
538 failure->start + failure->len - 1,
539 EXTENT_DIRTY | EXTENT_LOCKED,
540 GFP_NOFS);
541 kfree(failure);
542 }
543 }
509 return 0; 544 return 0;
510} 545}
511 546
@@ -547,26 +582,7 @@ int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
547 /* if the io failure tree for this inode is non-empty, 582 /* if the io failure tree for this inode is non-empty,
548 * check to see if we've recovered from a failed IO 583 * check to see if we've recovered from a failed IO
549 */ 584 */
550 private = 0; 585 btrfs_clean_io_failures(inode, start);
551 if (count_range_bits(&BTRFS_I(inode)->io_failure_tree, &private,
552 (u64)-1, 1, EXTENT_DIRTY)) {
553 u64 private_failure;
554 struct io_failure_record *failure;
555 ret = get_state_private(&BTRFS_I(inode)->io_failure_tree,
556 start, &private_failure);
557 if (ret == 0) {
558 failure = (struct io_failure_record *)(unsigned long)
559 private_failure;
560 set_state_private(&BTRFS_I(inode)->io_failure_tree,
561 failure->start, 0);
562 clear_extent_bits(&BTRFS_I(inode)->io_failure_tree,
563 failure->start,
564 failure->start + failure->len - 1,
565 EXTENT_DIRTY | EXTENT_LOCKED,
566 GFP_NOFS);
567 kfree(failure);
568 }
569 }
570 return 0; 586 return 0;
571 587
572zeroit: 588zeroit:
@@ -3657,7 +3673,7 @@ static struct extent_io_ops btrfs_extent_io_ops = {
3657 .merge_bio_hook = btrfs_merge_bio_hook, 3673 .merge_bio_hook = btrfs_merge_bio_hook,
3658 .readpage_io_hook = btrfs_readpage_io_hook, 3674 .readpage_io_hook = btrfs_readpage_io_hook,
3659 .readpage_end_io_hook = btrfs_readpage_end_io_hook, 3675 .readpage_end_io_hook = btrfs_readpage_end_io_hook,
3660 .readpage_io_failed_hook = btrfs_readpage_io_failed_hook, 3676 .readpage_io_failed_hook = btrfs_io_failed_hook,
3661 .set_bit_hook = btrfs_set_bit_hook, 3677 .set_bit_hook = btrfs_set_bit_hook,
3662 .clear_bit_hook = btrfs_clear_bit_hook, 3678 .clear_bit_hook = btrfs_clear_bit_hook,
3663}; 3679};