aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c8
-rw-r--r--drivers/md/raid10.c3
-rw-r--r--drivers/md/raid5.c29
-rw-r--r--include/linux/raid/md_k.h1
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
2510static void handle_stripe5(struct stripe_head *sh) 2510static 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
2759static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) 2762static 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
2972static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) 2977/* returns true if the stripe was handled */
2978static 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