diff options
Diffstat (limited to 'drivers/md/md.c')
| -rw-r--r-- | drivers/md/md.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index c7aae66c6f9b..8cfadc5bd2ba 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -2393,6 +2393,8 @@ static void analyze_sbs(mddev_t * mddev) | |||
| 2393 | 2393 | ||
| 2394 | } | 2394 | } |
| 2395 | 2395 | ||
| 2396 | static void md_safemode_timeout(unsigned long data); | ||
| 2397 | |||
| 2396 | static ssize_t | 2398 | static ssize_t |
| 2397 | safe_delay_show(mddev_t *mddev, char *page) | 2399 | safe_delay_show(mddev_t *mddev, char *page) |
| 2398 | { | 2400 | { |
| @@ -2432,9 +2434,12 @@ safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len) | |||
| 2432 | if (msec == 0) | 2434 | if (msec == 0) |
| 2433 | mddev->safemode_delay = 0; | 2435 | mddev->safemode_delay = 0; |
| 2434 | else { | 2436 | else { |
| 2437 | unsigned long old_delay = mddev->safemode_delay; | ||
| 2435 | mddev->safemode_delay = (msec*HZ)/1000; | 2438 | mddev->safemode_delay = (msec*HZ)/1000; |
| 2436 | if (mddev->safemode_delay == 0) | 2439 | if (mddev->safemode_delay == 0) |
| 2437 | mddev->safemode_delay = 1; | 2440 | mddev->safemode_delay = 1; |
| 2441 | if (mddev->safemode_delay < old_delay) | ||
| 2442 | md_safemode_timeout((unsigned long)mddev); | ||
| 2438 | } | 2443 | } |
| 2439 | return len; | 2444 | return len; |
| 2440 | } | 2445 | } |
| @@ -4634,6 +4639,11 @@ static int update_size(mddev_t *mddev, sector_t num_sectors) | |||
| 4634 | */ | 4639 | */ |
| 4635 | if (mddev->sync_thread) | 4640 | if (mddev->sync_thread) |
| 4636 | return -EBUSY; | 4641 | return -EBUSY; |
| 4642 | if (mddev->bitmap) | ||
| 4643 | /* Sorry, cannot grow a bitmap yet, just remove it, | ||
| 4644 | * grow, and re-add. | ||
| 4645 | */ | ||
| 4646 | return -EBUSY; | ||
| 4637 | rdev_for_each(rdev, tmp, mddev) { | 4647 | rdev_for_each(rdev, tmp, mddev) { |
| 4638 | sector_t avail; | 4648 | sector_t avail; |
| 4639 | avail = rdev->size * 2; | 4649 | avail = rdev->size * 2; |
| @@ -5993,7 +6003,7 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
| 5993 | } | 6003 | } |
| 5994 | } | 6004 | } |
| 5995 | 6005 | ||
| 5996 | if (mddev->degraded) { | 6006 | if (mddev->degraded && ! mddev->ro) { |
| 5997 | rdev_for_each(rdev, rtmp, mddev) { | 6007 | rdev_for_each(rdev, rtmp, mddev) { |
| 5998 | if (rdev->raid_disk >= 0 && | 6008 | if (rdev->raid_disk >= 0 && |
| 5999 | !test_bit(In_sync, &rdev->flags) && | 6009 | !test_bit(In_sync, &rdev->flags) && |
| @@ -6067,6 +6077,8 @@ void md_check_recovery(mddev_t *mddev) | |||
| 6067 | flush_signals(current); | 6077 | flush_signals(current); |
| 6068 | } | 6078 | } |
| 6069 | 6079 | ||
| 6080 | if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) | ||
| 6081 | return; | ||
| 6070 | if ( ! ( | 6082 | if ( ! ( |
| 6071 | (mddev->flags && !mddev->external) || | 6083 | (mddev->flags && !mddev->external) || |
| 6072 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || | 6084 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || |
| @@ -6080,6 +6092,15 @@ void md_check_recovery(mddev_t *mddev) | |||
| 6080 | if (mddev_trylock(mddev)) { | 6092 | if (mddev_trylock(mddev)) { |
| 6081 | int spares = 0; | 6093 | int spares = 0; |
| 6082 | 6094 | ||
| 6095 | if (mddev->ro) { | ||
| 6096 | /* Only thing we do on a ro array is remove | ||
| 6097 | * failed devices. | ||
| 6098 | */ | ||
| 6099 | remove_and_add_spares(mddev); | ||
| 6100 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
| 6101 | goto unlock; | ||
| 6102 | } | ||
| 6103 | |||
| 6083 | if (!mddev->external) { | 6104 | if (!mddev->external) { |
| 6084 | int did_change = 0; | 6105 | int did_change = 0; |
| 6085 | spin_lock_irq(&mddev->write_lock); | 6106 | spin_lock_irq(&mddev->write_lock); |
| @@ -6117,7 +6138,8 @@ void md_check_recovery(mddev_t *mddev) | |||
| 6117 | /* resync has finished, collect result */ | 6138 | /* resync has finished, collect result */ |
| 6118 | md_unregister_thread(mddev->sync_thread); | 6139 | md_unregister_thread(mddev->sync_thread); |
| 6119 | mddev->sync_thread = NULL; | 6140 | mddev->sync_thread = NULL; |
| 6120 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | 6141 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && |
| 6142 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | ||
| 6121 | /* success...*/ | 6143 | /* success...*/ |
| 6122 | /* activate any spares */ | 6144 | /* activate any spares */ |
| 6123 | if (mddev->pers->spare_active(mddev)) | 6145 | if (mddev->pers->spare_active(mddev)) |
| @@ -6169,6 +6191,7 @@ void md_check_recovery(mddev_t *mddev) | |||
| 6169 | } else if ((spares = remove_and_add_spares(mddev))) { | 6191 | } else if ((spares = remove_and_add_spares(mddev))) { |
| 6170 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | 6192 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
| 6171 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | 6193 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); |
| 6194 | clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); | ||
| 6172 | set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); | 6195 | set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); |
| 6173 | } else if (mddev->recovery_cp < MaxSector) { | 6196 | } else if (mddev->recovery_cp < MaxSector) { |
| 6174 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); | 6197 | set_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
| @@ -6232,7 +6255,11 @@ static int md_notify_reboot(struct notifier_block *this, | |||
| 6232 | 6255 | ||
| 6233 | for_each_mddev(mddev, tmp) | 6256 | for_each_mddev(mddev, tmp) |
| 6234 | if (mddev_trylock(mddev)) { | 6257 | if (mddev_trylock(mddev)) { |
| 6235 | do_md_stop (mddev, 1, 0); | 6258 | /* Force a switch to readonly even array |
| 6259 | * appears to still be in use. Hence | ||
| 6260 | * the '100'. | ||
| 6261 | */ | ||
| 6262 | do_md_stop (mddev, 1, 100); | ||
| 6236 | mddev_unlock(mddev); | 6263 | mddev_unlock(mddev); |
| 6237 | } | 6264 | } |
| 6238 | /* | 6265 | /* |
