Message ID | 20190327123901.12323-11-igor.j.konopko@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | lightnvm: next set of improvements for 5.2 | expand |
On 3/27/19 1:39 PM, Igor Konopko wrote: > This patch adds a counter, which is responsible for tracking inflight > target creations. > > When creation process is still in progress, target is not yet on > targets list. This causes a chance for removing whole lightnvm > subsystem by calling nvm_unregister() in the meantime and finally by > causing kernel panic inside target init function. > > With this patch we are able to track such a scenarios and wait with > completing nvm_unregister() and freeing memory until target creation > will be completed. > > Signed-off-by: Igor Konopko <igor.j.konopko@intel.com> > --- > drivers/lightnvm/core.c | 19 ++++++++++++++++++- > include/linux/lightnvm.h | 2 ++ > 2 files changed, 20 insertions(+), 1 deletion(-) > > diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c > index e2abe88..62ed662 100644 > --- a/drivers/lightnvm/core.c > +++ b/drivers/lightnvm/core.c > @@ -1083,6 +1083,7 @@ static int nvm_core_init(struct nvm_dev *dev) > INIT_LIST_HEAD(&dev->targets); > mutex_init(&dev->mlock); > spin_lock_init(&dev->lock); > + dev->create_inflight = 0; > > ret = nvm_register_map(dev); > if (ret) > @@ -1180,6 +1181,11 @@ void nvm_unregister(struct nvm_dev *dev) > struct nvm_target *t, *tmp; > > mutex_lock(&dev->mlock); > + while (dev->create_inflight > 0) { > + mutex_unlock(&dev->mlock); > + io_schedule(); > + mutex_lock(&dev->mlock); > + } > list_for_each_entry_safe(t, tmp, &dev->targets, list) { > if (t->dev->parent != dev) > continue; > @@ -1198,6 +1204,7 @@ EXPORT_SYMBOL(nvm_unregister); > static int __nvm_configure_create(struct nvm_ioctl_create *create) > { > struct nvm_dev *dev; > + int ret; > > down_write(&nvm_lock); > dev = nvm_find_nvm_dev(create->dev); > @@ -1208,7 +1215,17 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) > return -EINVAL; > } > > - return nvm_create_tgt(dev, create); > + mutex_lock(&dev->mlock); > + dev->create_inflight++; > + mutex_unlock(&dev->mlock); > + > + ret = nvm_create_tgt(dev, create); > + > + mutex_lock(&dev->mlock); > + dev->create_inflight--; > + mutex_unlock(&dev->mlock); > + > + return ret; > } > > static long nvm_ioctl_info(struct file *file, void __user *arg) > diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h > index d3b0270..e462d1d 100644 > --- a/include/linux/lightnvm.h > +++ b/include/linux/lightnvm.h > @@ -428,6 +428,8 @@ struct nvm_dev { > char name[DISK_NAME_LEN]; > void *private_data; > > + int create_inflight; > + > void *rmap; > > struct mutex mlock; > Hi Igor, I think this may be better implemented with kref. Such that target creator can take a reference upon target initialize and release it again afterwards. Then the one turning of the lights can get to run the final cleanup routine. -Matias
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index e2abe88..62ed662 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -1083,6 +1083,7 @@ static int nvm_core_init(struct nvm_dev *dev) INIT_LIST_HEAD(&dev->targets); mutex_init(&dev->mlock); spin_lock_init(&dev->lock); + dev->create_inflight = 0; ret = nvm_register_map(dev); if (ret) @@ -1180,6 +1181,11 @@ void nvm_unregister(struct nvm_dev *dev) struct nvm_target *t, *tmp; mutex_lock(&dev->mlock); + while (dev->create_inflight > 0) { + mutex_unlock(&dev->mlock); + io_schedule(); + mutex_lock(&dev->mlock); + } list_for_each_entry_safe(t, tmp, &dev->targets, list) { if (t->dev->parent != dev) continue; @@ -1198,6 +1204,7 @@ EXPORT_SYMBOL(nvm_unregister); static int __nvm_configure_create(struct nvm_ioctl_create *create) { struct nvm_dev *dev; + int ret; down_write(&nvm_lock); dev = nvm_find_nvm_dev(create->dev); @@ -1208,7 +1215,17 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) return -EINVAL; } - return nvm_create_tgt(dev, create); + mutex_lock(&dev->mlock); + dev->create_inflight++; + mutex_unlock(&dev->mlock); + + ret = nvm_create_tgt(dev, create); + + mutex_lock(&dev->mlock); + dev->create_inflight--; + mutex_unlock(&dev->mlock); + + return ret; } static long nvm_ioctl_info(struct file *file, void __user *arg) diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index d3b0270..e462d1d 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -428,6 +428,8 @@ struct nvm_dev { char name[DISK_NAME_LEN]; void *private_data; + int create_inflight; + void *rmap; struct mutex mlock;
This patch adds a counter, which is responsible for tracking inflight target creations. When creation process is still in progress, target is not yet on targets list. This causes a chance for removing whole lightnvm subsystem by calling nvm_unregister() in the meantime and finally by causing kernel panic inside target init function. With this patch we are able to track such a scenarios and wait with completing nvm_unregister() and freeing memory until target creation will be completed. Signed-off-by: Igor Konopko <igor.j.konopko@intel.com> --- drivers/lightnvm/core.c | 19 ++++++++++++++++++- include/linux/lightnvm.h | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-)