aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-12 06:44:03 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:39:01 -0400
commit8b110e393c5a6e72d50fcdf9fa7ed8b647cfdfc9 (patch)
tree36f6b0048c79fd63c55892cd45f0b78e8c0cc15b /fs/btrfs/disk-io.c
parent28e1cc7d1baf8038ae4ad4681c8f3dc94fcd7c00 (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.c11
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 &&