xen-blkback: don't leak stack data via response ring
[pandora-kernel.git] / drivers / md / dm.c
index 8953630..c00bcdc 100644 (file)
@@ -192,8 +192,8 @@ struct mapped_device {
        /* forced geometry settings */
        struct hd_geometry geometry;
 
-       /* sysfs handle */
-       struct kobject kobj;
+       /* kobject and completion */
+       struct dm_kobject_holder kobj_holder;
 
        /* zero-length flush that will be cloned and submitted to targets */
        struct bio flush_bio;
@@ -1891,6 +1891,7 @@ static struct mapped_device *alloc_dev(int minor)
        init_waitqueue_head(&md->wait);
        INIT_WORK(&md->work, dm_wq_work);
        init_waitqueue_head(&md->eventq);
+       init_completion(&md->kobj_holder.completion);
 
        md->disk->major = _major;
        md->disk->first_minor = minor;
@@ -2231,7 +2232,7 @@ int dm_setup_md_queue(struct mapped_device *md)
        return 0;
 }
 
-static struct mapped_device *dm_find_md(dev_t dev)
+struct mapped_device *dm_get_md(dev_t dev)
 {
        struct mapped_device *md;
        unsigned minor = MINOR(dev);
@@ -2242,12 +2243,15 @@ static struct mapped_device *dm_find_md(dev_t dev)
        spin_lock(&_minor_lock);
 
        md = idr_find(&_minor_idr, minor);
-       if (md && (md == MINOR_ALLOCED ||
-                  (MINOR(disk_devt(dm_disk(md))) != minor) ||
-                  dm_deleting_md(md) ||
-                  test_bit(DMF_FREEING, &md->flags))) {
-               md = NULL;
-               goto out;
+       if (md) {
+               if ((md == MINOR_ALLOCED ||
+                    (MINOR(disk_devt(dm_disk(md))) != minor) ||
+                    dm_deleting_md(md) ||
+                    test_bit(DMF_FREEING, &md->flags))) {
+                       md = NULL;
+                       goto out;
+               }
+               dm_get(md);
        }
 
 out:
@@ -2255,16 +2259,6 @@ out:
 
        return md;
 }
-
-struct mapped_device *dm_get_md(dev_t dev)
-{
-       struct mapped_device *md = dm_find_md(dev);
-
-       if (md)
-               dm_get(md);
-
-       return md;
-}
 EXPORT_SYMBOL_GPL(dm_get_md);
 
 void *dm_get_mdptr(struct mapped_device *md)
@@ -2301,10 +2295,16 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
        set_bit(DMF_FREEING, &md->flags);
        spin_unlock(&_minor_lock);
 
+       /*
+        * Take suspend_lock so that presuspend and postsuspend methods
+        * do not race with internal suspend.
+        */
+       mutex_lock(&md->suspend_lock);
        if (!dm_suspended_md(md)) {
                dm_table_presuspend_targets(map);
                dm_table_postsuspend_targets(map);
        }
+       mutex_unlock(&md->suspend_lock);
 
        /*
         * Rare, but there may be I/O requests still going to complete,
@@ -2682,7 +2682,7 @@ struct gendisk *dm_disk(struct mapped_device *md)
 
 struct kobject *dm_kobject(struct mapped_device *md)
 {
-       return &md->kobj;
+       return &md->kobj_holder.kobj;
 }
 
 /*
@@ -2693,9 +2693,7 @@ struct mapped_device *dm_get_from_kobject(struct kobject *kobj)
 {
        struct mapped_device *md;
 
-       md = container_of(kobj, struct mapped_device, kobj);
-       if (&md->kobj != kobj)
-               return NULL;
+       md = container_of(kobj, struct mapped_device, kobj_holder.kobj);
 
        if (test_bit(DMF_FREEING, &md->flags) ||
            dm_deleting_md(md))