lkml.org 
[lkml]   [2016]   [May]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 24/28] lightnvm: remove mgt targets on mgt removal
    Date
    Targets associated with a device manager are not freed on device
    removal. They have to be manually removed before shutdown. Make sure
    any outstanding targets are freed upon shutdown.

    Signed-off-by: Matias Bjørling <m@bjorling.me>
    ---
    drivers/lightnvm/core.c | 69 ++++++++++++++++++++++++++++++------------------
    include/linux/lightnvm.h | 1 +
    2 files changed, 44 insertions(+), 26 deletions(-)

    diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
    index 1873a3b..d3af771 100644
    --- a/drivers/lightnvm/core.c
    +++ b/drivers/lightnvm/core.c
    @@ -596,13 +596,52 @@ err_fmtype:
    return ret;
    }

    +static void nvm_remove_target(struct nvm_target *t)
    +{
    + struct nvm_tgt_type *tt = t->type;
    + struct gendisk *tdisk = t->disk;
    + struct request_queue *q = tdisk->queue;
    +
    + lockdep_assert_held(&nvm_lock);
    +
    + del_gendisk(tdisk);
    + blk_cleanup_queue(q);
    +
    + if (tt->exit)
    + tt->exit(tdisk->private_data);
    +
    + put_disk(tdisk);
    +
    + list_del(&t->list);
    + kfree(t);
    +}
    +
    +static void nvm_free_mgr(struct nvm_dev *dev)
    +{
    + struct nvm_target *tgt, *tmp;
    +
    + if (!dev->mt)
    + return;
    +
    + down_write(&nvm_lock);
    + list_for_each_entry_safe(tgt, tmp, &nvm_targets, list) {
    + if (tgt->dev != dev)
    + continue;
    +
    + nvm_remove_target(tgt);
    + }
    + up_write(&nvm_lock);
    +
    + dev->mt->unregister_mgr(dev);
    + dev->mt = NULL;
    +}
    +
    static void nvm_free(struct nvm_dev *dev)
    {
    if (!dev)
    return;

    - if (dev->mt)
    - dev->mt->unregister_mgr(dev);
    + nvm_free_mgr(dev);

    kfree(dev->lptbl);
    kfree(dev->lun_map);
    @@ -808,6 +847,7 @@ static int nvm_create_target(struct nvm_dev *dev,

    t->type = tt;
    t->disk = tdisk;
    + t->dev = dev;

    down_write(&nvm_lock);
    list_add_tail(&t->list, &nvm_targets);
    @@ -823,26 +863,6 @@ err_t:
    return -ENOMEM;
    }

    -static void nvm_remove_target(struct nvm_target *t)
    -{
    - struct nvm_tgt_type *tt = t->type;
    - struct gendisk *tdisk = t->disk;
    - struct request_queue *q = tdisk->queue;
    -
    - lockdep_assert_held(&nvm_lock);
    -
    - del_gendisk(tdisk);
    - blk_cleanup_queue(q);
    -
    - if (tt->exit)
    - tt->exit(tdisk->private_data);
    -
    - put_disk(tdisk);
    -
    - list_del(&t->list);
    - kfree(t);
    -}
    -
    static int __nvm_configure_create(struct nvm_ioctl_create *create)
    {
    struct nvm_dev *dev;
    @@ -1231,10 +1251,7 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg)
    return -EINVAL;
    }

    - if (dev->mt) {
    - dev->mt->unregister_mgr(dev);
    - dev->mt = NULL;
    - }
    + nvm_free_mgr(dev);

    if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT)
    return nvm_dev_factory(dev, fact.flags);
    diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h
    index 0e8e019..cde31ff 100644
    --- a/include/linux/lightnvm.h
    +++ b/include/linux/lightnvm.h
    @@ -200,6 +200,7 @@ struct nvm_id {

    struct nvm_target {
    struct list_head list;
    + struct nvm_dev *dev;
    struct nvm_tgt_type *type;
    struct gendisk *disk;
    };
    --
    2.1.4
    \
     
     \ /
      Last update: 2016-05-06 20:21    [W:4.193 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site