aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-04-14 20:13:47 -0400
committerNeilBrown <neilb@suse.de>2010-05-17 00:40:07 -0400
commitb6eb127d274385d81ce8dd45c98190f097bce1b4 (patch)
treea78eb14056ade77c0026b1106e9a2cd486a762e6 /drivers/md/md.c
parentef2f80ff7325b2c1888ff02ead28957b5840bf51 (diff)
md: remove unneeded sysfs files more promptly
When an array is stopped we need to remove some sysfs files which are dependent on the type of array. We need to delay that deletion as deleting them while holding reconfig_mutex can lead to deadlocks. We currently delay them until the array is completely destroyed. However it is possible to deactivate and then reactivate the array. It is also possible to need to remove sysfs files when changing level, which can potentially happen several times before an array is destroyed. So we need to delete these files more promptly: as soon as reconfig_mutex is dropped. We need to ensure this happens before do_md_run can restart the array, so we use open_mutex for some extra locking. This is not deadlock prone. Cc: stable@kernel.org Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 08f665178c3b..edf777f6fe56 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -507,9 +507,32 @@ static inline int mddev_trylock(mddev_t * mddev)
507 return mutex_trylock(&mddev->reconfig_mutex); 507 return mutex_trylock(&mddev->reconfig_mutex);
508} 508}
509 509
510static struct attribute_group md_redundancy_group;
511
510static inline void mddev_unlock(mddev_t * mddev) 512static inline void mddev_unlock(mddev_t * mddev)
511{ 513{
512 mutex_unlock(&mddev->reconfig_mutex); 514 if (mddev->pers == NULL && mddev->private) {
515 /* These cannot be removed under reconfig_mutex as
516 * an access to the files will try to take reconfig_mutex
517 * while holding the file unremovable, which leads to
518 * a deadlock.
519 * So hold open_mutex instead - we are allowed to take
520 * it while holding reconfig_mutex, and md_run can
521 * use it to wait for the remove to complete.
522 */
523 mutex_lock(&mddev->open_mutex);
524 mutex_unlock(&mddev->reconfig_mutex);
525
526 sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
527 if (mddev->private != (void*)1)
528 sysfs_remove_group(&mddev->kobj, mddev->private);
529 if (mddev->sysfs_action)
530 sysfs_put(mddev->sysfs_action);
531 mddev->sysfs_action = NULL;
532 mddev->private = NULL;
533 mutex_unlock(&mddev->open_mutex);
534 } else
535 mutex_unlock(&mddev->reconfig_mutex);
513 536
514 md_wakeup_thread(mddev->thread); 537 md_wakeup_thread(mddev->thread);
515} 538}
@@ -4075,15 +4098,6 @@ static void mddev_delayed_delete(struct work_struct *ws)
4075{ 4098{
4076 mddev_t *mddev = container_of(ws, mddev_t, del_work); 4099 mddev_t *mddev = container_of(ws, mddev_t, del_work);
4077 4100
4078 if (mddev->private) {
4079 sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
4080 if (mddev->private != (void*)1)
4081 sysfs_remove_group(&mddev->kobj, mddev->private);
4082 if (mddev->sysfs_action)
4083 sysfs_put(mddev->sysfs_action);
4084 mddev->sysfs_action = NULL;
4085 mddev->private = NULL;
4086 }
4087 sysfs_remove_group(&mddev->kobj, &md_bitmap_group); 4101 sysfs_remove_group(&mddev->kobj, &md_bitmap_group);
4088 kobject_del(&mddev->kobj); 4102 kobject_del(&mddev->kobj);
4089 kobject_put(&mddev->kobj); 4103 kobject_put(&mddev->kobj);
@@ -4241,6 +4255,13 @@ static int do_md_run(mddev_t * mddev)
4241 if (mddev->pers) 4255 if (mddev->pers)
4242 return -EBUSY; 4256 return -EBUSY;
4243 4257
4258 /* These two calls synchronise us with the
4259 * sysfs_remove_group calls in mddev_unlock,
4260 * so they must have completed.
4261 */
4262 mutex_lock(&mddev->open_mutex);
4263 mutex_unlock(&mddev->open_mutex);
4264
4244 /* 4265 /*
4245 * Analyze all RAID superblock(s) 4266 * Analyze all RAID superblock(s)
4246 */ 4267 */