lkml.org 
[lkml]   [2014]   [Feb]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.13 053/120] dm: wait until embedded kobject is released before destroying a device
    Date
    3.13-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Mikulas Patocka <mpatocka@redhat.com>

    commit be35f486108227e10fe5d96fd42fb2b344c59983 upstream.

    There may be other parts of the kernel holding a reference on the dm
    kobject. We must wait until all references are dropped before
    deallocating the mapped_device structure.

    The dm_kobject_release method signals that all references are dropped
    via completion. But dm_kobject_release doesn't free the kobject (which
    is embedded in the mapped_device structure).

    This is the sequence of operations:
    * when destroying a DM device, call kobject_put from dm_sysfs_exit
    * wait until all users stop using the kobject, when it happens the
    release method is called
    * the release method signals the completion and should return without
    delay
    * the dm device removal code that waits on the completion continues
    * the dm device removal code drops the dm_mod reference the device had
    * the dm device removal code frees the mapped_device structure that
    contains the kobject

    Using kobject this way should avoid the module unload race that was
    mentioned at the beginning of this thread:
    https://lkml.org/lkml/2014/1/4/83

    Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
    Signed-off-by: Mike Snitzer <snitzer@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/md/dm-sysfs.c | 10 +++++++++-
    drivers/md/dm.c | 11 +++++++++++
    drivers/md/dm.h | 2 ++
    3 files changed, 22 insertions(+), 1 deletion(-)

    --- a/drivers/md/dm-sysfs.c
    +++ b/drivers/md/dm-sysfs.c
    @@ -79,6 +79,11 @@ static const struct sysfs_ops dm_sysfs_o
    .show = dm_attr_show,
    };

    +static void dm_kobject_release(struct kobject *kobj)
    +{
    + complete(dm_get_completion_from_kobject(kobj));
    +}
    +
    /*
    * dm kobject is embedded in mapped_device structure
    * no need to define release function here
    @@ -86,6 +91,7 @@ static const struct sysfs_ops dm_sysfs_o
    static struct kobj_type dm_ktype = {
    .sysfs_ops = &dm_sysfs_ops,
    .default_attrs = dm_attrs,
    + .release = dm_kobject_release,
    };

    /*
    @@ -104,5 +110,7 @@ int dm_sysfs_init(struct mapped_device *
    */
    void dm_sysfs_exit(struct mapped_device *md)
    {
    - kobject_put(dm_kobject(md));
    + struct kobject *kobj = dm_kobject(md);
    + kobject_put(kobj);
    + wait_for_completion(dm_get_completion_from_kobject(kobj));
    }
    --- a/drivers/md/dm.c
    +++ b/drivers/md/dm.c
    @@ -203,6 +203,9 @@ struct mapped_device {
    /* sysfs handle */
    struct kobject kobj;

    + /* wait until the kobject is released */
    + struct completion kobj_completion;
    +
    /* zero-length flush that will be cloned and submitted to targets */
    struct bio flush_bio;

    @@ -2041,6 +2044,7 @@ static struct mapped_device *alloc_dev(i
    init_waitqueue_head(&md->wait);
    INIT_WORK(&md->work, dm_wq_work);
    init_waitqueue_head(&md->eventq);
    + init_completion(&md->kobj_completion);

    md->disk->major = _major;
    md->disk->first_minor = minor;
    @@ -2925,6 +2929,13 @@ struct mapped_device *dm_get_from_kobjec
    return md;
    }

    +struct completion *dm_get_completion_from_kobject(struct kobject *kobj)
    +{
    + struct mapped_device *md = container_of(kobj, struct mapped_device, kobj);
    +
    + return &md->kobj_completion;
    +}
    +
    int dm_suspended_md(struct mapped_device *md)
    {
    return test_bit(DMF_SUSPENDED, &md->flags);
    --- a/drivers/md/dm.h
    +++ b/drivers/md/dm.h
    @@ -15,6 +15,7 @@
    #include <linux/list.h>
    #include <linux/blkdev.h>
    #include <linux/hdreg.h>
    +#include <linux/completion.h>

    #include "dm-stats.h"

    @@ -152,6 +153,7 @@ int dm_sysfs_init(struct mapped_device *
    void dm_sysfs_exit(struct mapped_device *md);
    struct kobject *dm_kobject(struct mapped_device *md);
    struct mapped_device *dm_get_from_kobject(struct kobject *kobj);
    +struct completion *dm_get_completion_from_kobject(struct kobject *kobj);

    /*
    * Targets for linear and striped mappings



    \
     
     \ /
      Last update: 2014-02-13 03:01    [W:4.271 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site