diff options
Diffstat (limited to 'drivers/md/raid5-cache.c')
-rw-r--r-- | drivers/md/raid5-cache.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 26ba09282e7c..4c00bc248287 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "md.h" | 24 | #include "md.h" |
25 | #include "raid5.h" | 25 | #include "raid5.h" |
26 | #include "bitmap.h" | 26 | #include "bitmap.h" |
27 | #include "raid5-log.h" | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * metadata/data stored in disk with 4k size unit (a block) regardless | 30 | * metadata/data stored in disk with 4k size unit (a block) regardless |
@@ -622,20 +623,30 @@ static void r5l_do_submit_io(struct r5l_log *log, struct r5l_io_unit *io) | |||
622 | __r5l_set_io_unit_state(io, IO_UNIT_IO_START); | 623 | __r5l_set_io_unit_state(io, IO_UNIT_IO_START); |
623 | spin_unlock_irqrestore(&log->io_list_lock, flags); | 624 | spin_unlock_irqrestore(&log->io_list_lock, flags); |
624 | 625 | ||
626 | /* | ||
627 | * In case of journal device failures, submit_bio will get error | ||
628 | * and calls endio, then active stripes will continue write | ||
629 | * process. Therefore, it is not necessary to check Faulty bit | ||
630 | * of journal device here. | ||
631 | * | ||
632 | * We can't check split_bio after current_bio is submitted. If | ||
633 | * io->split_bio is null, after current_bio is submitted, current_bio | ||
634 | * might already be completed and the io_unit is freed. We submit | ||
635 | * split_bio first to avoid the issue. | ||
636 | */ | ||
637 | if (io->split_bio) { | ||
638 | if (io->has_flush) | ||
639 | io->split_bio->bi_opf |= REQ_PREFLUSH; | ||
640 | if (io->has_fua) | ||
641 | io->split_bio->bi_opf |= REQ_FUA; | ||
642 | submit_bio(io->split_bio); | ||
643 | } | ||
644 | |||
625 | if (io->has_flush) | 645 | if (io->has_flush) |
626 | io->current_bio->bi_opf |= REQ_PREFLUSH; | 646 | io->current_bio->bi_opf |= REQ_PREFLUSH; |
627 | if (io->has_fua) | 647 | if (io->has_fua) |
628 | io->current_bio->bi_opf |= REQ_FUA; | 648 | io->current_bio->bi_opf |= REQ_FUA; |
629 | submit_bio(io->current_bio); | 649 | submit_bio(io->current_bio); |
630 | |||
631 | if (!io->split_bio) | ||
632 | return; | ||
633 | |||
634 | if (io->has_flush) | ||
635 | io->split_bio->bi_opf |= REQ_PREFLUSH; | ||
636 | if (io->has_fua) | ||
637 | io->split_bio->bi_opf |= REQ_FUA; | ||
638 | submit_bio(io->split_bio); | ||
639 | } | 650 | } |
640 | 651 | ||
641 | /* deferred io_unit will be dispatched here */ | 652 | /* deferred io_unit will be dispatched here */ |
@@ -670,6 +681,11 @@ static void r5c_disable_writeback_async(struct work_struct *work) | |||
670 | return; | 681 | return; |
671 | pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n", | 682 | pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n", |
672 | mdname(mddev)); | 683 | mdname(mddev)); |
684 | |||
685 | /* wait superblock change before suspend */ | ||
686 | wait_event(mddev->sb_wait, | ||
687 | !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)); | ||
688 | |||
673 | mddev_suspend(mddev); | 689 | mddev_suspend(mddev); |
674 | log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH; | 690 | log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH; |
675 | mddev_resume(mddev); | 691 | mddev_resume(mddev); |
@@ -2621,8 +2637,11 @@ int r5c_try_caching_write(struct r5conf *conf, | |||
2621 | * When run in degraded mode, array is set to write-through mode. | 2637 | * When run in degraded mode, array is set to write-through mode. |
2622 | * This check helps drain pending write safely in the transition to | 2638 | * This check helps drain pending write safely in the transition to |
2623 | * write-through mode. | 2639 | * write-through mode. |
2640 | * | ||
2641 | * When a stripe is syncing, the write is also handled in write | ||
2642 | * through mode. | ||
2624 | */ | 2643 | */ |
2625 | if (s->failed) { | 2644 | if (s->failed || test_bit(STRIPE_SYNCING, &sh->state)) { |
2626 | r5c_make_stripe_write_out(sh); | 2645 | r5c_make_stripe_write_out(sh); |
2627 | return -EAGAIN; | 2646 | return -EAGAIN; |
2628 | } | 2647 | } |
@@ -2825,6 +2844,9 @@ void r5c_finish_stripe_write_out(struct r5conf *conf, | |||
2825 | } | 2844 | } |
2826 | 2845 | ||
2827 | r5l_append_flush_payload(log, sh->sector); | 2846 | r5l_append_flush_payload(log, sh->sector); |
2847 | /* stripe is flused to raid disks, we can do resync now */ | ||
2848 | if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) | ||
2849 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2828 | } | 2850 | } |
2829 | 2851 | ||
2830 | int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh) | 2852 | int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh) |
@@ -2973,7 +2995,7 @@ ioerr: | |||
2973 | return ret; | 2995 | return ret; |
2974 | } | 2996 | } |
2975 | 2997 | ||
2976 | void r5c_update_on_rdev_error(struct mddev *mddev) | 2998 | void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev) |
2977 | { | 2999 | { |
2978 | struct r5conf *conf = mddev->private; | 3000 | struct r5conf *conf = mddev->private; |
2979 | struct r5l_log *log = conf->log; | 3001 | struct r5l_log *log = conf->log; |
@@ -2981,7 +3003,8 @@ void r5c_update_on_rdev_error(struct mddev *mddev) | |||
2981 | if (!log) | 3003 | if (!log) |
2982 | return; | 3004 | return; |
2983 | 3005 | ||
2984 | if (raid5_calc_degraded(conf) > 0 && | 3006 | if ((raid5_calc_degraded(conf) > 0 || |
3007 | test_bit(Journal, &rdev->flags)) && | ||
2985 | conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK) | 3008 | conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK) |
2986 | schedule_work(&log->disable_writeback_work); | 3009 | schedule_work(&log->disable_writeback_work); |
2987 | } | 3010 | } |