diff options
-rw-r--r-- | drivers/md/md.c | 8 | ||||
-rw-r--r-- | drivers/md/raid10.c | 3 | ||||
-rw-r--r-- | drivers/md/raid5.c | 29 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 1 |
4 files changed, 28 insertions, 13 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index c2ff77ccec50..c7aae66c6f9b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3483,7 +3483,7 @@ static void md_safemode_timeout(unsigned long data) | |||
3483 | if (!atomic_read(&mddev->writes_pending)) { | 3483 | if (!atomic_read(&mddev->writes_pending)) { |
3484 | mddev->safemode = 1; | 3484 | mddev->safemode = 1; |
3485 | if (mddev->external) | 3485 | if (mddev->external) |
3486 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | 3486 | set_bit(MD_NOTIFY_ARRAY_STATE, &mddev->flags); |
3487 | } | 3487 | } |
3488 | md_wakeup_thread(mddev->thread); | 3488 | md_wakeup_thread(mddev->thread); |
3489 | } | 3489 | } |
@@ -5996,7 +5996,8 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5996 | if (mddev->degraded) { | 5996 | if (mddev->degraded) { |
5997 | rdev_for_each(rdev, rtmp, mddev) { | 5997 | rdev_for_each(rdev, rtmp, mddev) { |
5998 | if (rdev->raid_disk >= 0 && | 5998 | if (rdev->raid_disk >= 0 && |
5999 | !test_bit(In_sync, &rdev->flags)) | 5999 | !test_bit(In_sync, &rdev->flags) && |
6000 | !test_bit(Blocked, &rdev->flags)) | ||
6000 | spares++; | 6001 | spares++; |
6001 | if (rdev->raid_disk < 0 | 6002 | if (rdev->raid_disk < 0 |
6002 | && !test_bit(Faulty, &rdev->flags)) { | 6003 | && !test_bit(Faulty, &rdev->flags)) { |
@@ -6051,6 +6052,9 @@ void md_check_recovery(mddev_t *mddev) | |||
6051 | if (mddev->bitmap) | 6052 | if (mddev->bitmap) |
6052 | bitmap_daemon_work(mddev->bitmap); | 6053 | bitmap_daemon_work(mddev->bitmap); |
6053 | 6054 | ||
6055 | if (test_and_clear_bit(MD_NOTIFY_ARRAY_STATE, &mddev->flags)) | ||
6056 | sysfs_notify(&mddev->kobj, NULL, "array_state"); | ||
6057 | |||
6054 | if (mddev->ro) | 6058 | if (mddev->ro) |
6055 | return; | 6059 | return; |
6056 | 6060 | ||
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 159535d73567..d41bebb6da0f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -215,6 +215,9 @@ static void reschedule_retry(r10bio_t *r10_bio) | |||
215 | conf->nr_queued ++; | 215 | conf->nr_queued ++; |
216 | spin_unlock_irqrestore(&conf->device_lock, flags); | 216 | spin_unlock_irqrestore(&conf->device_lock, flags); |
217 | 217 | ||
218 | /* wake up frozen array... */ | ||
219 | wake_up(&conf->wait_barrier); | ||
220 | |||
218 | md_wakeup_thread(mddev->thread); | 221 | md_wakeup_thread(mddev->thread); |
219 | } | 222 | } |
220 | 223 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 55e7c56045a0..40e939675657 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2507,7 +2507,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, | |||
2507 | * | 2507 | * |
2508 | */ | 2508 | */ |
2509 | 2509 | ||
2510 | static void handle_stripe5(struct stripe_head *sh) | 2510 | static bool handle_stripe5(struct stripe_head *sh) |
2511 | { | 2511 | { |
2512 | raid5_conf_t *conf = sh->raid_conf; | 2512 | raid5_conf_t *conf = sh->raid_conf; |
2513 | int disks = sh->disks, i; | 2513 | int disks = sh->disks, i; |
@@ -2717,10 +2717,11 @@ static void handle_stripe5(struct stripe_head *sh) | |||
2717 | if (sh->reconstruct_state == reconstruct_state_result) { | 2717 | if (sh->reconstruct_state == reconstruct_state_result) { |
2718 | sh->reconstruct_state = reconstruct_state_idle; | 2718 | sh->reconstruct_state = reconstruct_state_idle; |
2719 | clear_bit(STRIPE_EXPANDING, &sh->state); | 2719 | clear_bit(STRIPE_EXPANDING, &sh->state); |
2720 | for (i = conf->raid_disks; i--; ) | 2720 | for (i = conf->raid_disks; i--; ) { |
2721 | set_bit(R5_Wantwrite, &sh->dev[i].flags); | 2721 | set_bit(R5_Wantwrite, &sh->dev[i].flags); |
2722 | set_bit(R5_LOCKED, &dev->flags); | 2722 | set_bit(R5_LOCKED, &sh->dev[i].flags); |
2723 | s.locked++; | 2723 | s.locked++; |
2724 | } | ||
2724 | } | 2725 | } |
2725 | 2726 | ||
2726 | if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) && | 2727 | if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) && |
@@ -2754,9 +2755,11 @@ static void handle_stripe5(struct stripe_head *sh) | |||
2754 | ops_run_io(sh, &s); | 2755 | ops_run_io(sh, &s); |
2755 | 2756 | ||
2756 | return_io(return_bi); | 2757 | return_io(return_bi); |
2758 | |||
2759 | return blocked_rdev == NULL; | ||
2757 | } | 2760 | } |
2758 | 2761 | ||
2759 | static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | 2762 | static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) |
2760 | { | 2763 | { |
2761 | raid6_conf_t *conf = sh->raid_conf; | 2764 | raid6_conf_t *conf = sh->raid_conf; |
2762 | int disks = sh->disks; | 2765 | int disks = sh->disks; |
@@ -2967,14 +2970,17 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
2967 | ops_run_io(sh, &s); | 2970 | ops_run_io(sh, &s); |
2968 | 2971 | ||
2969 | return_io(return_bi); | 2972 | return_io(return_bi); |
2973 | |||
2974 | return blocked_rdev == NULL; | ||
2970 | } | 2975 | } |
2971 | 2976 | ||
2972 | static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) | 2977 | /* returns true if the stripe was handled */ |
2978 | static bool handle_stripe(struct stripe_head *sh, struct page *tmp_page) | ||
2973 | { | 2979 | { |
2974 | if (sh->raid_conf->level == 6) | 2980 | if (sh->raid_conf->level == 6) |
2975 | handle_stripe6(sh, tmp_page); | 2981 | return handle_stripe6(sh, tmp_page); |
2976 | else | 2982 | else |
2977 | handle_stripe5(sh); | 2983 | return handle_stripe5(sh); |
2978 | } | 2984 | } |
2979 | 2985 | ||
2980 | 2986 | ||
@@ -3692,7 +3698,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3692 | clear_bit(STRIPE_INSYNC, &sh->state); | 3698 | clear_bit(STRIPE_INSYNC, &sh->state); |
3693 | spin_unlock(&sh->lock); | 3699 | spin_unlock(&sh->lock); |
3694 | 3700 | ||
3695 | handle_stripe(sh, NULL); | 3701 | /* wait for any blocked device to be handled */ |
3702 | while(unlikely(!handle_stripe(sh, NULL))) | ||
3703 | ; | ||
3696 | release_stripe(sh); | 3704 | release_stripe(sh); |
3697 | 3705 | ||
3698 | return STRIPE_SECTORS; | 3706 | return STRIPE_SECTORS; |
@@ -3811,10 +3819,8 @@ static void raid5d(mddev_t *mddev) | |||
3811 | 3819 | ||
3812 | sh = __get_priority_stripe(conf); | 3820 | sh = __get_priority_stripe(conf); |
3813 | 3821 | ||
3814 | if (!sh) { | 3822 | if (!sh) |
3815 | async_tx_issue_pending_all(); | ||
3816 | break; | 3823 | break; |
3817 | } | ||
3818 | spin_unlock_irq(&conf->device_lock); | 3824 | spin_unlock_irq(&conf->device_lock); |
3819 | 3825 | ||
3820 | handled++; | 3826 | handled++; |
@@ -3827,6 +3833,7 @@ static void raid5d(mddev_t *mddev) | |||
3827 | 3833 | ||
3828 | spin_unlock_irq(&conf->device_lock); | 3834 | spin_unlock_irq(&conf->device_lock); |
3829 | 3835 | ||
3836 | async_tx_issue_pending_all(); | ||
3830 | unplug_slaves(mddev); | 3837 | unplug_slaves(mddev); |
3831 | 3838 | ||
3832 | pr_debug("--- raid5d inactive\n"); | 3839 | pr_debug("--- raid5d inactive\n"); |
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 9f2549ac0e2d..c200b9a34aff 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
@@ -128,6 +128,7 @@ struct mddev_s | |||
128 | #define MD_CHANGE_DEVS 0 /* Some device status has changed */ | 128 | #define MD_CHANGE_DEVS 0 /* Some device status has changed */ |
129 | #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ | 129 | #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ |
130 | #define MD_CHANGE_PENDING 2 /* superblock update in progress */ | 130 | #define MD_CHANGE_PENDING 2 /* superblock update in progress */ |
131 | #define MD_NOTIFY_ARRAY_STATE 3 /* atomic context wants to notify userspace */ | ||
131 | 132 | ||
132 | int ro; | 133 | int ro; |
133 | 134 | ||