diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 56 |
1 files changed, 16 insertions, 40 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index f4f5f82f9f53..a20a71e5efd3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -386,7 +386,9 @@ static void mddev_put(mddev_t *mddev) | |||
386 | if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) | 386 | if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) |
387 | return; | 387 | return; |
388 | if (!mddev->raid_disks && list_empty(&mddev->disks) && | 388 | if (!mddev->raid_disks && list_empty(&mddev->disks) && |
389 | !mddev->hold_active) { | 389 | mddev->ctime == 0 && !mddev->hold_active) { |
390 | /* Array is not configured at all, and not held active, | ||
391 | * so destroy it */ | ||
390 | list_del(&mddev->all_mddevs); | 392 | list_del(&mddev->all_mddevs); |
391 | if (mddev->gendisk) { | 393 | if (mddev->gendisk) { |
392 | /* we did a probe so need to clean up. | 394 | /* we did a probe so need to clean up. |
@@ -4073,8 +4075,10 @@ static void mddev_delayed_delete(struct work_struct *ws) | |||
4073 | { | 4075 | { |
4074 | mddev_t *mddev = container_of(ws, mddev_t, del_work); | 4076 | mddev_t *mddev = container_of(ws, mddev_t, del_work); |
4075 | 4077 | ||
4076 | if (mddev->private == &md_redundancy_group) { | 4078 | if (mddev->private) { |
4077 | sysfs_remove_group(&mddev->kobj, &md_redundancy_group); | 4079 | sysfs_remove_group(&mddev->kobj, &md_redundancy_group); |
4080 | if (mddev->private != (void*)1) | ||
4081 | sysfs_remove_group(&mddev->kobj, mddev->private); | ||
4078 | if (mddev->sysfs_action) | 4082 | if (mddev->sysfs_action) |
4079 | sysfs_put(mddev->sysfs_action); | 4083 | sysfs_put(mddev->sysfs_action); |
4080 | mddev->sysfs_action = NULL; | 4084 | mddev->sysfs_action = NULL; |
@@ -4285,10 +4289,7 @@ static int do_md_run(mddev_t * mddev) | |||
4285 | sysfs_notify_dirent(rdev->sysfs_state); | 4289 | sysfs_notify_dirent(rdev->sysfs_state); |
4286 | } | 4290 | } |
4287 | 4291 | ||
4288 | md_probe(mddev->unit, NULL, NULL); | ||
4289 | disk = mddev->gendisk; | 4292 | disk = mddev->gendisk; |
4290 | if (!disk) | ||
4291 | return -ENOMEM; | ||
4292 | 4293 | ||
4293 | spin_lock(&pers_lock); | 4294 | spin_lock(&pers_lock); |
4294 | pers = find_pers(mddev->level, mddev->clevel); | 4295 | pers = find_pers(mddev->level, mddev->clevel); |
@@ -4355,7 +4356,7 @@ static int do_md_run(mddev_t * mddev) | |||
4355 | mddev->barriers_work = 1; | 4356 | mddev->barriers_work = 1; |
4356 | mddev->ok_start_degraded = start_dirty_degraded; | 4357 | mddev->ok_start_degraded = start_dirty_degraded; |
4357 | 4358 | ||
4358 | if (start_readonly) | 4359 | if (start_readonly && mddev->ro == 0) |
4359 | mddev->ro = 2; /* read-only, but switch on first write */ | 4360 | mddev->ro = 2; /* read-only, but switch on first write */ |
4360 | 4361 | ||
4361 | err = mddev->pers->run(mddev); | 4362 | err = mddev->pers->run(mddev); |
@@ -4419,33 +4420,6 @@ static int do_md_run(mddev_t * mddev) | |||
4419 | 4420 | ||
4420 | set_capacity(disk, mddev->array_sectors); | 4421 | set_capacity(disk, mddev->array_sectors); |
4421 | 4422 | ||
4422 | /* If there is a partially-recovered drive we need to | ||
4423 | * start recovery here. If we leave it to md_check_recovery, | ||
4424 | * it will remove the drives and not do the right thing | ||
4425 | */ | ||
4426 | if (mddev->degraded && !mddev->sync_thread) { | ||
4427 | int spares = 0; | ||
4428 | list_for_each_entry(rdev, &mddev->disks, same_set) | ||
4429 | if (rdev->raid_disk >= 0 && | ||
4430 | !test_bit(In_sync, &rdev->flags) && | ||
4431 | !test_bit(Faulty, &rdev->flags)) | ||
4432 | /* complete an interrupted recovery */ | ||
4433 | spares++; | ||
4434 | if (spares && mddev->pers->sync_request) { | ||
4435 | mddev->recovery = 0; | ||
4436 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | ||
4437 | mddev->sync_thread = md_register_thread(md_do_sync, | ||
4438 | mddev, | ||
4439 | "resync"); | ||
4440 | if (!mddev->sync_thread) { | ||
4441 | printk(KERN_ERR "%s: could not start resync" | ||
4442 | " thread...\n", | ||
4443 | mdname(mddev)); | ||
4444 | /* leave the spares where they are, it shouldn't hurt */ | ||
4445 | mddev->recovery = 0; | ||
4446 | } | ||
4447 | } | ||
4448 | } | ||
4449 | md_wakeup_thread(mddev->thread); | 4423 | md_wakeup_thread(mddev->thread); |
4450 | md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ | 4424 | md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ |
4451 | 4425 | ||
@@ -4555,8 +4529,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
4555 | mddev->queue->unplug_fn = NULL; | 4529 | mddev->queue->unplug_fn = NULL; |
4556 | mddev->queue->backing_dev_info.congested_fn = NULL; | 4530 | mddev->queue->backing_dev_info.congested_fn = NULL; |
4557 | module_put(mddev->pers->owner); | 4531 | module_put(mddev->pers->owner); |
4558 | if (mddev->pers->sync_request) | 4532 | if (mddev->pers->sync_request && mddev->private == NULL) |
4559 | mddev->private = &md_redundancy_group; | 4533 | mddev->private = (void*)1; |
4560 | mddev->pers = NULL; | 4534 | mddev->pers = NULL; |
4561 | /* tell userspace to handle 'inactive' */ | 4535 | /* tell userspace to handle 'inactive' */ |
4562 | sysfs_notify_dirent(mddev->sysfs_state); | 4536 | sysfs_notify_dirent(mddev->sysfs_state); |
@@ -4603,9 +4577,6 @@ out: | |||
4603 | } | 4577 | } |
4604 | mddev->bitmap_info.offset = 0; | 4578 | mddev->bitmap_info.offset = 0; |
4605 | 4579 | ||
4606 | /* make sure all md_delayed_delete calls have finished */ | ||
4607 | flush_scheduled_work(); | ||
4608 | |||
4609 | export_array(mddev); | 4580 | export_array(mddev); |
4610 | 4581 | ||
4611 | mddev->array_sectors = 0; | 4582 | mddev->array_sectors = 0; |
@@ -5262,6 +5233,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) | |||
5262 | mddev->minor_version = info->minor_version; | 5233 | mddev->minor_version = info->minor_version; |
5263 | mddev->patch_version = info->patch_version; | 5234 | mddev->patch_version = info->patch_version; |
5264 | mddev->persistent = !info->not_persistent; | 5235 | mddev->persistent = !info->not_persistent; |
5236 | /* ensure mddev_put doesn't delete this now that there | ||
5237 | * is some minimal configuration. | ||
5238 | */ | ||
5239 | mddev->ctime = get_seconds(); | ||
5265 | return 0; | 5240 | return 0; |
5266 | } | 5241 | } |
5267 | mddev->major_version = MD_MAJOR_VERSION; | 5242 | mddev->major_version = MD_MAJOR_VERSION; |
@@ -6494,10 +6469,11 @@ void md_do_sync(mddev_t *mddev) | |||
6494 | mddev->curr_resync = 2; | 6469 | mddev->curr_resync = 2; |
6495 | 6470 | ||
6496 | try_again: | 6471 | try_again: |
6497 | if (kthread_should_stop()) { | 6472 | if (kthread_should_stop()) |
6498 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 6473 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
6474 | |||
6475 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) | ||
6499 | goto skip; | 6476 | goto skip; |
6500 | } | ||
6501 | for_each_mddev(mddev2, tmp) { | 6477 | for_each_mddev(mddev2, tmp) { |
6502 | if (mddev2 == mddev) | 6478 | if (mddev2 == mddev) |
6503 | continue; | 6479 | continue; |