diff options
| -rw-r--r-- | drivers/md/md.c | 31 | ||||
| -rw-r--r-- | drivers/md/md.h | 4 |
2 files changed, 21 insertions, 14 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 00c3fde39a12..03dcbfbe250f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -580,13 +580,17 @@ static void mddev_unlock(mddev_t * mddev) | |||
| 580 | * an access to the files will try to take reconfig_mutex | 580 | * an access to the files will try to take reconfig_mutex |
| 581 | * while holding the file unremovable, which leads to | 581 | * while holding the file unremovable, which leads to |
| 582 | * a deadlock. | 582 | * a deadlock. |
| 583 | * So hold open_mutex instead - we are allowed to take | 583 | * So hold set sysfs_active while the remove in happeing, |
| 584 | * it while holding reconfig_mutex, and md_run can | 584 | * and anything else which might set ->to_remove or my |
| 585 | * use it to wait for the remove to complete. | 585 | * otherwise change the sysfs namespace will fail with |
| 586 | * -EBUSY if sysfs_active is still set. | ||
| 587 | * We set sysfs_active under reconfig_mutex and elsewhere | ||
| 588 | * test it under the same mutex to ensure its correct value | ||
| 589 | * is seen. | ||
| 586 | */ | 590 | */ |
| 587 | struct attribute_group *to_remove = mddev->to_remove; | 591 | struct attribute_group *to_remove = mddev->to_remove; |
| 588 | mddev->to_remove = NULL; | 592 | mddev->to_remove = NULL; |
| 589 | mutex_lock(&mddev->open_mutex); | 593 | mddev->sysfs_active = 1; |
| 590 | mutex_unlock(&mddev->reconfig_mutex); | 594 | mutex_unlock(&mddev->reconfig_mutex); |
| 591 | 595 | ||
| 592 | if (mddev->kobj.sd) { | 596 | if (mddev->kobj.sd) { |
| @@ -600,7 +604,7 @@ static void mddev_unlock(mddev_t * mddev) | |||
| 600 | mddev->sysfs_action = NULL; | 604 | mddev->sysfs_action = NULL; |
| 601 | } | 605 | } |
| 602 | } | 606 | } |
| 603 | mutex_unlock(&mddev->open_mutex); | 607 | mddev->sysfs_active = 0; |
| 604 | } else | 608 | } else |
| 605 | mutex_unlock(&mddev->reconfig_mutex); | 609 | mutex_unlock(&mddev->reconfig_mutex); |
| 606 | 610 | ||
| @@ -3008,7 +3012,9 @@ level_store(mddev_t *mddev, const char *buf, size_t len) | |||
| 3008 | * - new personality will access other array. | 3012 | * - new personality will access other array. |
| 3009 | */ | 3013 | */ |
| 3010 | 3014 | ||
| 3011 | if (mddev->sync_thread || mddev->reshape_position != MaxSector) | 3015 | if (mddev->sync_thread || |
| 3016 | mddev->reshape_position != MaxSector || | ||
| 3017 | mddev->sysfs_active) | ||
| 3012 | return -EBUSY; | 3018 | return -EBUSY; |
| 3013 | 3019 | ||
| 3014 | if (!mddev->pers->quiesce) { | 3020 | if (!mddev->pers->quiesce) { |
| @@ -4393,13 +4399,9 @@ int md_run(mddev_t *mddev) | |||
| 4393 | 4399 | ||
| 4394 | if (mddev->pers) | 4400 | if (mddev->pers) |
| 4395 | return -EBUSY; | 4401 | return -EBUSY; |
| 4396 | 4402 | /* Cannot run until previous stop completes properly */ | |
| 4397 | /* These two calls synchronise us with the | 4403 | if (mddev->sysfs_active) |
| 4398 | * sysfs_remove_group calls in mddev_unlock, | 4404 | return -EBUSY; |
| 4399 | * so they must have completed. | ||
| 4400 | */ | ||
| 4401 | mutex_lock(&mddev->open_mutex); | ||
| 4402 | mutex_unlock(&mddev->open_mutex); | ||
| 4403 | 4405 | ||
| 4404 | /* | 4406 | /* |
| 4405 | * Analyze all RAID superblock(s) | 4407 | * Analyze all RAID superblock(s) |
| @@ -4770,7 +4772,8 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
| 4770 | mdk_rdev_t *rdev; | 4772 | mdk_rdev_t *rdev; |
| 4771 | 4773 | ||
| 4772 | mutex_lock(&mddev->open_mutex); | 4774 | mutex_lock(&mddev->open_mutex); |
| 4773 | if (atomic_read(&mddev->openers) > is_open) { | 4775 | if (atomic_read(&mddev->openers) > is_open || |
| 4776 | mddev->sysfs_active) { | ||
| 4774 | printk("md: %s still in use.\n",mdname(mddev)); | 4777 | printk("md: %s still in use.\n",mdname(mddev)); |
| 4775 | err = -EBUSY; | 4778 | err = -EBUSY; |
| 4776 | } else if (mddev->pers) { | 4779 | } else if (mddev->pers) { |
diff --git a/drivers/md/md.h b/drivers/md/md.h index cccbadb31bae..6f797eceae31 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -145,6 +145,10 @@ struct mddev_s | |||
| 145 | int suspended; | 145 | int suspended; |
| 146 | atomic_t active_io; | 146 | atomic_t active_io; |
| 147 | int ro; | 147 | int ro; |
| 148 | int sysfs_active; /* set when sysfs deletes | ||
| 149 | * are happening, so run/ | ||
| 150 | * takeover/stop are not safe | ||
| 151 | */ | ||
| 148 | 152 | ||
| 149 | struct gendisk *gendisk; | 153 | struct gendisk *gendisk; |
| 150 | 154 | ||
