aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c43
-rw-r--r--drivers/md/md.h1
-rw-r--r--drivers/md/raid5.c7
3 files changed, 38 insertions, 13 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);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 8e4c75c00d46..722f5dfe1953 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -305,6 +305,7 @@ struct mddev_s
305 atomic_t max_corr_read_errors; /* max read retries */ 305 atomic_t max_corr_read_errors; /* max read retries */
306 struct list_head all_mddevs; 306 struct list_head all_mddevs;
307 307
308 struct attribute_group *to_remove;
308 /* Generic barrier handling. 309 /* Generic barrier handling.
309 * If there is a pending barrier request, all other 310 * If there is a pending barrier request, all other
310 * writes are blocked while the devices are flushed. 311 * writes are blocked while the devices are flushed.
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 70ffbd071b2e..a361398875d0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5090,7 +5090,9 @@ static int run(mddev_t *mddev)
5090 } 5090 }
5091 5091
5092 /* Ok, everything is just fine now */ 5092 /* Ok, everything is just fine now */
5093 if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group)) 5093 if (mddev->to_remove == &raid5_attrs_group)
5094 mddev->to_remove = NULL;
5095 else if (sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
5094 printk(KERN_WARNING 5096 printk(KERN_WARNING
5095 "raid5: failed to create sysfs attributes for %s\n", 5097 "raid5: failed to create sysfs attributes for %s\n",
5096 mdname(mddev)); 5098 mdname(mddev));
@@ -5137,7 +5139,8 @@ static int stop(mddev_t *mddev)
5137 mddev->queue->backing_dev_info.congested_fn = NULL; 5139 mddev->queue->backing_dev_info.congested_fn = NULL;
5138 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ 5140 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
5139 free_conf(conf); 5141 free_conf(conf);
5140 mddev->private = &raid5_attrs_group; 5142 mddev->private = NULL;
5143 mddev->to_remove = &raid5_attrs_group;
5141 return 0; 5144 return 0;
5142} 5145}
5143 5146