diff options
author | Matias Bjørling <m@bjorling.me> | 2016-05-06 14:03:17 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2016-05-06 14:51:10 -0400 |
commit | 976bdfcae32ea10c2c8c2ecaeb0d85873f634dad (patch) | |
tree | 479ceab3d7330f9acd8d64353ed2c238311171c1 /drivers/lightnvm/core.c | |
parent | 45bbd0529e5d50aa91a4bb5fffffc5e24df3ef7e (diff) |
lightnvm: remove mgt targets on mgt removal
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>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r-- | drivers/lightnvm/core.c | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 1873a3bc913d..d3af77102e47 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c | |||
@@ -596,13 +596,52 @@ err_fmtype: | |||
596 | return ret; | 596 | return ret; |
597 | } | 597 | } |
598 | 598 | ||
599 | static void nvm_remove_target(struct nvm_target *t) | ||
600 | { | ||
601 | struct nvm_tgt_type *tt = t->type; | ||
602 | struct gendisk *tdisk = t->disk; | ||
603 | struct request_queue *q = tdisk->queue; | ||
604 | |||
605 | lockdep_assert_held(&nvm_lock); | ||
606 | |||
607 | del_gendisk(tdisk); | ||
608 | blk_cleanup_queue(q); | ||
609 | |||
610 | if (tt->exit) | ||
611 | tt->exit(tdisk->private_data); | ||
612 | |||
613 | put_disk(tdisk); | ||
614 | |||
615 | list_del(&t->list); | ||
616 | kfree(t); | ||
617 | } | ||
618 | |||
619 | static void nvm_free_mgr(struct nvm_dev *dev) | ||
620 | { | ||
621 | struct nvm_target *tgt, *tmp; | ||
622 | |||
623 | if (!dev->mt) | ||
624 | return; | ||
625 | |||
626 | down_write(&nvm_lock); | ||
627 | list_for_each_entry_safe(tgt, tmp, &nvm_targets, list) { | ||
628 | if (tgt->dev != dev) | ||
629 | continue; | ||
630 | |||
631 | nvm_remove_target(tgt); | ||
632 | } | ||
633 | up_write(&nvm_lock); | ||
634 | |||
635 | dev->mt->unregister_mgr(dev); | ||
636 | dev->mt = NULL; | ||
637 | } | ||
638 | |||
599 | static void nvm_free(struct nvm_dev *dev) | 639 | static void nvm_free(struct nvm_dev *dev) |
600 | { | 640 | { |
601 | if (!dev) | 641 | if (!dev) |
602 | return; | 642 | return; |
603 | 643 | ||
604 | if (dev->mt) | 644 | nvm_free_mgr(dev); |
605 | dev->mt->unregister_mgr(dev); | ||
606 | 645 | ||
607 | kfree(dev->lptbl); | 646 | kfree(dev->lptbl); |
608 | kfree(dev->lun_map); | 647 | kfree(dev->lun_map); |
@@ -808,6 +847,7 @@ static int nvm_create_target(struct nvm_dev *dev, | |||
808 | 847 | ||
809 | t->type = tt; | 848 | t->type = tt; |
810 | t->disk = tdisk; | 849 | t->disk = tdisk; |
850 | t->dev = dev; | ||
811 | 851 | ||
812 | down_write(&nvm_lock); | 852 | down_write(&nvm_lock); |
813 | list_add_tail(&t->list, &nvm_targets); | 853 | list_add_tail(&t->list, &nvm_targets); |
@@ -823,26 +863,6 @@ err_t: | |||
823 | return -ENOMEM; | 863 | return -ENOMEM; |
824 | } | 864 | } |
825 | 865 | ||
826 | static void nvm_remove_target(struct nvm_target *t) | ||
827 | { | ||
828 | struct nvm_tgt_type *tt = t->type; | ||
829 | struct gendisk *tdisk = t->disk; | ||
830 | struct request_queue *q = tdisk->queue; | ||
831 | |||
832 | lockdep_assert_held(&nvm_lock); | ||
833 | |||
834 | del_gendisk(tdisk); | ||
835 | blk_cleanup_queue(q); | ||
836 | |||
837 | if (tt->exit) | ||
838 | tt->exit(tdisk->private_data); | ||
839 | |||
840 | put_disk(tdisk); | ||
841 | |||
842 | list_del(&t->list); | ||
843 | kfree(t); | ||
844 | } | ||
845 | |||
846 | static int __nvm_configure_create(struct nvm_ioctl_create *create) | 866 | static int __nvm_configure_create(struct nvm_ioctl_create *create) |
847 | { | 867 | { |
848 | struct nvm_dev *dev; | 868 | struct nvm_dev *dev; |
@@ -1231,10 +1251,7 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg) | |||
1231 | return -EINVAL; | 1251 | return -EINVAL; |
1232 | } | 1252 | } |
1233 | 1253 | ||
1234 | if (dev->mt) { | 1254 | nvm_free_mgr(dev); |
1235 | dev->mt->unregister_mgr(dev); | ||
1236 | dev->mt = NULL; | ||
1237 | } | ||
1238 | 1255 | ||
1239 | if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) | 1256 | if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) |
1240 | return nvm_dev_factory(dev, fact.flags); | 1257 | return nvm_dev_factory(dev, fact.flags); |