aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c43
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
510static struct attribute_group md_redundancy_group; 510static struct attribute_group md_redundancy_group;
511 511
512static inline void mddev_unlock(mddev_t * mddev) 512static 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);