diff options
-rw-r--r-- | drivers/md/md.c | 43 | ||||
-rw-r--r-- | drivers/md/md.h | 1 | ||||
-rw-r--r-- | drivers/md/raid5.c | 7 |
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 | ||
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); |
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 | ||