diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index edf777f6fe56..e8d238885cd2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -509,9 +509,9 @@ static inline int mddev_trylock(mddev_t * mddev) | |||
509 | 509 | ||
510 | static struct attribute_group md_redundancy_group; | 510 | static struct attribute_group md_redundancy_group; |
511 | 511 | ||
512 | static inline void mddev_unlock(mddev_t * mddev) | 512 | static void mddev_unlock(mddev_t * mddev) |
513 | { | 513 | { |
514 | if (mddev->pers == NULL && mddev->private) { | 514 | if (mddev->to_remove) { |
515 | /* These cannot be removed under reconfig_mutex as | 515 | /* These cannot be removed under reconfig_mutex as |
516 | * an access to the files will try to take reconfig_mutex | 516 | * an access to the files will try to take reconfig_mutex |
517 | * while holding the file unremovable, which leads to | 517 | * while holding the file unremovable, which leads to |
@@ -520,16 +520,20 @@ static inline void mddev_unlock(mddev_t * mddev) | |||
520 | * it while holding reconfig_mutex, and md_run can | 520 | * it while holding reconfig_mutex, and md_run can |
521 | * use it to wait for the remove to complete. | 521 | * use it to wait for the remove to complete. |
522 | */ | 522 | */ |
523 | struct attribute_group *to_remove = mddev->to_remove; | ||
524 | mddev->to_remove = NULL; | ||
523 | mutex_lock(&mddev->open_mutex); | 525 | mutex_lock(&mddev->open_mutex); |
524 | mutex_unlock(&mddev->reconfig_mutex); | 526 | mutex_unlock(&mddev->reconfig_mutex); |
525 | 527 | ||
526 | sysfs_remove_group(&mddev->kobj, &md_redundancy_group); | 528 | if (to_remove != &md_redundancy_group) |
527 | if (mddev->private != (void*)1) | 529 | sysfs_remove_group(&mddev->kobj, to_remove); |
528 | sysfs_remove_group(&mddev->kobj, mddev->private); | 530 | if (mddev->pers == NULL || |
529 | if (mddev->sysfs_action) | 531 | mddev->pers->sync_request == NULL) { |
530 | sysfs_put(mddev->sysfs_action); | 532 | sysfs_remove_group(&mddev->kobj, &md_redundancy_group); |
531 | mddev->sysfs_action = NULL; | 533 | if (mddev->sysfs_action) |
532 | mddev->private = NULL; | 534 | sysfs_put(mddev->sysfs_action); |
535 | mddev->sysfs_action = NULL; | ||
536 | } | ||
533 | mutex_unlock(&mddev->open_mutex); | 537 | mutex_unlock(&mddev->open_mutex); |
534 | } else | 538 | } else |
535 | mutex_unlock(&mddev->reconfig_mutex); | 539 | mutex_unlock(&mddev->reconfig_mutex); |
@@ -2996,6 +3000,23 @@ level_store(mddev_t *mddev, const char *buf, size_t len) | |||
2996 | /* Looks like we have a winner */ | 3000 | /* Looks like we have a winner */ |
2997 | mddev_suspend(mddev); | 3001 | mddev_suspend(mddev); |
2998 | mddev->pers->stop(mddev); | 3002 | mddev->pers->stop(mddev); |
3003 | |||
3004 | if (mddev->pers->sync_request == NULL && | ||
3005 | pers->sync_request != NULL) { | ||
3006 | /* need to add the md_redundancy_group */ | ||
3007 | if (sysfs_create_group(&mddev->kobj, &md_redundancy_group)) | ||
3008 | printk(KERN_WARNING | ||
3009 | "md: cannot register extra attributes for %s\n", | ||
3010 | mdname(mddev)); | ||
3011 | mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action"); | ||
3012 | } | ||
3013 | if (mddev->pers->sync_request != NULL && | ||
3014 | pers->sync_request == NULL) { | ||
3015 | /* need to remove the md_redundancy_group */ | ||
3016 | if (mddev->to_remove == NULL) | ||
3017 | mddev->to_remove = &md_redundancy_group; | ||
3018 | } | ||
3019 | |||
2999 | module_put(mddev->pers->owner); | 3020 | module_put(mddev->pers->owner); |
3000 | /* Invalidate devices that are now superfluous */ | 3021 | /* Invalidate devices that are now superfluous */ |
3001 | list_for_each_entry(rdev, &mddev->disks, same_set) | 3022 | list_for_each_entry(rdev, &mddev->disks, same_set) |
@@ -4550,8 +4571,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
4550 | mddev->queue->unplug_fn = NULL; | 4571 | mddev->queue->unplug_fn = NULL; |
4551 | mddev->queue->backing_dev_info.congested_fn = NULL; | 4572 | mddev->queue->backing_dev_info.congested_fn = NULL; |
4552 | module_put(mddev->pers->owner); | 4573 | module_put(mddev->pers->owner); |
4553 | if (mddev->pers->sync_request && mddev->private == NULL) | 4574 | if (mddev->pers->sync_request && mddev->to_remove == NULL) |
4554 | mddev->private = (void*)1; | 4575 | mddev->to_remove = &md_redundancy_group; |
4555 | mddev->pers = NULL; | 4576 | mddev->pers = NULL; |
4556 | /* tell userspace to handle 'inactive' */ | 4577 | /* tell userspace to handle 'inactive' */ |
4557 | sysfs_notify_dirent(mddev->sysfs_state); | 4578 | sysfs_notify_dirent(mddev->sysfs_state); |