summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-03-09 20:50:11 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-03-09 20:50:11 -0700
commitbad948ffee7cbf73a7dd3e4b8272985d5c3c8b55 (patch)
tree0bc675ff15d51bac630f03acaeb157aef0ede280 /drivers
parent99adcd9d67aaf04e28f5ae96df280f236bde4b66 (diff)
parent5fd3a17ed456637a224cf4ca82b9ad9d005bc8d4 (diff)
downloadlinux-bad948ffee7cbf73a7dd3e4b8272985d5c3c8b55.tar.bz2
Merge branch 'for-linus' of git://neil.brown.name/md
* 'for-linus' of git://neil.brown.name/md: md: fix deadlock when stopping arrays
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/md.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 03b4cd0a6344..a307f87eb90e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -214,12 +214,7 @@ static inline mddev_t *mddev_get(mddev_t *mddev)
return mddev;
}
-static void mddev_delayed_delete(struct work_struct *ws)
-{
- mddev_t *mddev = container_of(ws, mddev_t, del_work);
- kobject_del(&mddev->kobj);
- kobject_put(&mddev->kobj);
-}
+static void mddev_delayed_delete(struct work_struct *ws);
static void mddev_put(mddev_t *mddev)
{
@@ -3542,6 +3537,21 @@ static struct kobj_type md_ktype = {
int mdp_major = 0;
+static void mddev_delayed_delete(struct work_struct *ws)
+{
+ mddev_t *mddev = container_of(ws, mddev_t, del_work);
+
+ if (mddev->private == &md_redundancy_group) {
+ sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
+ if (mddev->sysfs_action)
+ sysfs_put(mddev->sysfs_action);
+ mddev->sysfs_action = NULL;
+ mddev->private = NULL;
+ }
+ kobject_del(&mddev->kobj);
+ kobject_put(&mddev->kobj);
+}
+
static int md_alloc(dev_t dev, char *name)
{
static DEFINE_MUTEX(disks_mutex);
@@ -4033,13 +4043,9 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
mddev->queue->merge_bvec_fn = NULL;
mddev->queue->unplug_fn = NULL;
mddev->queue->backing_dev_info.congested_fn = NULL;
- if (mddev->pers->sync_request) {
- sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
- if (mddev->sysfs_action)
- sysfs_put(mddev->sysfs_action);
- mddev->sysfs_action = NULL;
- }
module_put(mddev->pers->owner);
+ if (mddev->pers->sync_request)
+ mddev->private = &md_redundancy_group;
mddev->pers = NULL;
/* tell userspace to handle 'inactive' */
sysfs_notify_dirent(mddev->sysfs_state);