diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2014-09-12 06:44:03 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-09-17 16:39:01 -0400 |
commit | 8b110e393c5a6e72d50fcdf9fa7ed8b647cfdfc9 (patch) | |
tree | 36f6b0048c79fd63c55892cd45f0b78e8c0cc15b /fs/btrfs/disk-io.c | |
parent | 28e1cc7d1baf8038ae4ad4681c8f3dc94fcd7c00 (diff) |
Btrfs: implement repair function when direct read fails
This patch implement data repair function when direct read fails.
The detail of the implementation is:
- When we find the data is not right, we try to read the data from the other
mirror.
- When the io on the mirror ends, we will insert the endio work into the
dedicated btrfs workqueue, not common read endio workqueue, because the
original endio work is still blocked in the btrfs endio workqueue, if we
insert the endio work of the io on the mirror into that workqueue, deadlock
would happen.
- After we get right data, we write it back to the corrupted mirror.
- And if the data on the new mirror is still corrupted, we will try next
mirror until we read right data or all the mirrors are traversed.
- After the above work, we set the uptodate flag according to the result.
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a224fb9b34a3..48794f951427 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -713,7 +713,11 @@ static void end_workqueue_bio(struct bio *bio, int err) | |||
713 | func = btrfs_endio_write_helper; | 713 | func = btrfs_endio_write_helper; |
714 | } | 714 | } |
715 | } else { | 715 | } else { |
716 | if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) { | 716 | if (unlikely(end_io_wq->metadata == |
717 | BTRFS_WQ_ENDIO_DIO_REPAIR)) { | ||
718 | wq = fs_info->endio_repair_workers; | ||
719 | func = btrfs_endio_repair_helper; | ||
720 | } else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) { | ||
717 | wq = fs_info->endio_raid56_workers; | 721 | wq = fs_info->endio_raid56_workers; |
718 | func = btrfs_endio_raid56_helper; | 722 | func = btrfs_endio_raid56_helper; |
719 | } else if (end_io_wq->metadata) { | 723 | } else if (end_io_wq->metadata) { |
@@ -741,6 +745,7 @@ int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, | |||
741 | int metadata) | 745 | int metadata) |
742 | { | 746 | { |
743 | struct end_io_wq *end_io_wq; | 747 | struct end_io_wq *end_io_wq; |
748 | |||
744 | end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS); | 749 | end_io_wq = kmalloc(sizeof(*end_io_wq), GFP_NOFS); |
745 | if (!end_io_wq) | 750 | if (!end_io_wq) |
746 | return -ENOMEM; | 751 | return -ENOMEM; |
@@ -2055,6 +2060,7 @@ static void btrfs_stop_all_workers(struct btrfs_fs_info *fs_info) | |||
2055 | btrfs_destroy_workqueue(fs_info->endio_workers); | 2060 | btrfs_destroy_workqueue(fs_info->endio_workers); |
2056 | btrfs_destroy_workqueue(fs_info->endio_meta_workers); | 2061 | btrfs_destroy_workqueue(fs_info->endio_meta_workers); |
2057 | btrfs_destroy_workqueue(fs_info->endio_raid56_workers); | 2062 | btrfs_destroy_workqueue(fs_info->endio_raid56_workers); |
2063 | btrfs_destroy_workqueue(fs_info->endio_repair_workers); | ||
2058 | btrfs_destroy_workqueue(fs_info->rmw_workers); | 2064 | btrfs_destroy_workqueue(fs_info->rmw_workers); |
2059 | btrfs_destroy_workqueue(fs_info->endio_meta_write_workers); | 2065 | btrfs_destroy_workqueue(fs_info->endio_meta_write_workers); |
2060 | btrfs_destroy_workqueue(fs_info->endio_write_workers); | 2066 | btrfs_destroy_workqueue(fs_info->endio_write_workers); |
@@ -2572,6 +2578,8 @@ int open_ctree(struct super_block *sb, | |||
2572 | btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2); | 2578 | btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2); |
2573 | fs_info->endio_raid56_workers = | 2579 | fs_info->endio_raid56_workers = |
2574 | btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4); | 2580 | btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4); |
2581 | fs_info->endio_repair_workers = | ||
2582 | btrfs_alloc_workqueue("endio-repair", flags, 1, 0); | ||
2575 | fs_info->rmw_workers = | 2583 | fs_info->rmw_workers = |
2576 | btrfs_alloc_workqueue("rmw", flags, max_active, 2); | 2584 | btrfs_alloc_workqueue("rmw", flags, max_active, 2); |
2577 | fs_info->endio_write_workers = | 2585 | fs_info->endio_write_workers = |
@@ -2593,6 +2601,7 @@ int open_ctree(struct super_block *sb, | |||
2593 | fs_info->submit_workers && fs_info->flush_workers && | 2601 | fs_info->submit_workers && fs_info->flush_workers && |
2594 | fs_info->endio_workers && fs_info->endio_meta_workers && | 2602 | fs_info->endio_workers && fs_info->endio_meta_workers && |
2595 | fs_info->endio_meta_write_workers && | 2603 | fs_info->endio_meta_write_workers && |
2604 | fs_info->endio_repair_workers && | ||
2596 | fs_info->endio_write_workers && fs_info->endio_raid56_workers && | 2605 | fs_info->endio_write_workers && fs_info->endio_raid56_workers && |
2597 | fs_info->endio_freespace_worker && fs_info->rmw_workers && | 2606 | fs_info->endio_freespace_worker && fs_info->rmw_workers && |
2598 | fs_info->caching_workers && fs_info->readahead_workers && | 2607 | fs_info->caching_workers && fs_info->readahead_workers && |