From a14669ebc0e294f19b2290c294958b7741559d9d Mon Sep 17 00:00:00 2001 From: Igor Konopko Date: Sat, 4 May 2019 20:37:55 +0200 Subject: lightnvm: Inherit mdts from the parent nvme device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current lightnvm and pblk implementation does not care about NVMe max data transfer size, which can be smaller than 64*K=256K. There are existing NVMe controllers which NVMe max data transfer size is lower that 256K (for example 128K, which happens for existing NVMe controllers which are NVMe spec compliant). Such a controllers are not able to handle command which contains 64 PPAs, since the the size of DMAed buffer will be above the capabilities of such a controller. Signed-off-by: Igor Konopko Reviewed-by: Hans Holmberg Reviewed-by: Javier González Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- include/linux/lightnvm.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 5d865a5d5cdc..d3b02708e5f0 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -358,6 +358,7 @@ struct nvm_geo { u16 csecs; /* sector size */ u16 sos; /* out-of-band area size */ bool ext; /* metadata in extended data buffer */ + u32 mdts; /* Max data transfer size*/ /* device write constrains */ u32 ws_min; /* minimum write size */ -- cgit v1.2.3 From e69397ea05ce0263e3ee72fa8f6f70d2d9a561a7 Mon Sep 17 00:00:00 2001 From: Igor Konopko Date: Sat, 4 May 2019 20:38:08 +0200 Subject: lightnvm: track inflight target creations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. This patch changes the behaviour by adding kref variable which tracks all the users of nvm_dev structure. When nvm_dev is allocated, kref value is set to 1. Then before every target creation the value is increased and decreased after target removal. The extra reference is decreased when nvm subsystem is unregistered. Signed-off-by: Igor Konopko Reviewed-by: Javier González Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 41 +++++++++++++++++++++++++++++++---------- include/linux/lightnvm.h | 1 + 2 files changed, 32 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index e2abe88a139c..0e9f7996ff1d 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -45,6 +45,8 @@ struct nvm_dev_map { int num_ch; }; +static void nvm_free(struct kref *ref); + static struct nvm_target *nvm_find_target(struct nvm_dev *dev, const char *name) { struct nvm_target *tgt; @@ -501,6 +503,7 @@ static int nvm_remove_tgt(struct nvm_dev *dev, struct nvm_ioctl_remove *remove) } __nvm_remove_target(t, true); mutex_unlock(&dev->mlock); + kref_put(&dev->ref, nvm_free); return 0; } @@ -1094,15 +1097,16 @@ err_fmtype: return ret; } -static void nvm_free(struct nvm_dev *dev) +static void nvm_free(struct kref *ref) { - if (!dev) - return; + struct nvm_dev *dev = container_of(ref, struct nvm_dev, ref); if (dev->dma_pool) dev->ops->destroy_dma_pool(dev->dma_pool); - nvm_unregister_map(dev); + if (dev->rmap) + nvm_unregister_map(dev); + kfree(dev->lun_map); kfree(dev); } @@ -1139,7 +1143,13 @@ err: struct nvm_dev *nvm_alloc_dev(int node) { - return kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node); + struct nvm_dev *dev; + + dev = kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node); + if (dev) + kref_init(&dev->ref); + + return dev; } EXPORT_SYMBOL(nvm_alloc_dev); @@ -1147,12 +1157,16 @@ int nvm_register(struct nvm_dev *dev) { int ret, exp_pool_size; - if (!dev->q || !dev->ops) + if (!dev->q || !dev->ops) { + kref_put(&dev->ref, nvm_free); return -EINVAL; + } ret = nvm_init(dev); - if (ret) + if (ret) { + kref_put(&dev->ref, nvm_free); return ret; + } exp_pool_size = max_t(int, PAGE_SIZE, (NVM_MAX_VLBA * (sizeof(u64) + dev->geo.sos))); @@ -1162,7 +1176,7 @@ int nvm_register(struct nvm_dev *dev) exp_pool_size); if (!dev->dma_pool) { pr_err("nvm: could not create dma pool\n"); - nvm_free(dev); + kref_put(&dev->ref, nvm_free); return -ENOMEM; } @@ -1184,6 +1198,7 @@ void nvm_unregister(struct nvm_dev *dev) if (t->dev->parent != dev) continue; __nvm_remove_target(t, false); + kref_put(&dev->ref, nvm_free); } mutex_unlock(&dev->mlock); @@ -1191,13 +1206,14 @@ void nvm_unregister(struct nvm_dev *dev) list_del(&dev->devices); up_write(&nvm_lock); - nvm_free(dev); + kref_put(&dev->ref, nvm_free); } 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 +1224,12 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) return -EINVAL; } - return nvm_create_tgt(dev, create); + kref_get(&dev->ref); + ret = nvm_create_tgt(dev, create); + if (ret) + kref_put(&dev->ref, nvm_free); + + 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 d3b02708e5f0..4d0d5655c7b2 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -428,6 +428,7 @@ struct nvm_dev { char name[DISK_NAME_LEN]; void *private_data; + struct kref ref; void *rmap; struct mutex mlock; -- cgit v1.2.3 From 9581ae4f0facf122a732841959812dea9ed2f422 Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Sat, 11 May 2019 22:42:54 +0900 Subject: nvme: fix typos in nvme status code values Fix typos in enumeration names for nvme status: s/ACIVATE/ACTIVATE/ s/INSUFFICENT/INSUFFICIENT/ Signed-off-by: Minwoo Im Reviewed-by: Sagi Grimberg Reviewed-by: Chaitanya Kulkarni Signed-off-by: Christoph Hellwig --- include/linux/nvme.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/nvme.h b/include/linux/nvme.h index c40720cb59ac..8028adacaff3 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -1246,9 +1246,9 @@ enum { NVME_SC_FW_NEEDS_SUBSYS_RESET = 0x110, NVME_SC_FW_NEEDS_RESET = 0x111, NVME_SC_FW_NEEDS_MAX_TIME = 0x112, - NVME_SC_FW_ACIVATE_PROHIBITED = 0x113, + NVME_SC_FW_ACTIVATE_PROHIBITED = 0x113, NVME_SC_OVERLAPPING_RANGE = 0x114, - NVME_SC_NS_INSUFFICENT_CAP = 0x115, + NVME_SC_NS_INSUFFICIENT_CAP = 0x115, NVME_SC_NS_ID_UNAVAILABLE = 0x116, NVME_SC_NS_ALREADY_ATTACHED = 0x118, NVME_SC_NS_IS_PRIVATE = 0x119, -- cgit v1.2.3