Commit d22524a4 authored by Christoph Hellwig's avatar Christoph Hellwig

nvme: switch controller refcounting to use struct device

Instead of allocating a separate struct device for the character device
handle embedd it into struct nvme_ctrl and use it for the main controller
refcounting.  This removes double refcounting and gets us an automatic
reference for the character device operations.  We keep ctrl->device as a
pointer for now to avoid chaning printks all over, but in the future we
could look into message printing helpers that take a controller structure
similar to what other subsystems do.

Note the delete_ctrl operation always already has a reference (either
through sysfs due this change, or because every open file on the
/dev/nvme-fabrics node has a refernece) when it is entered now, so we
don't need to do the unless_zero variant there.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
parent c6424a90
...@@ -1915,7 +1915,7 @@ static int nvme_dev_open(struct inode *inode, struct file *file) ...@@ -1915,7 +1915,7 @@ static int nvme_dev_open(struct inode *inode, struct file *file)
ret = -EWOULDBLOCK; ret = -EWOULDBLOCK;
break; break;
} }
if (!kref_get_unless_zero(&ctrl->kref)) if (!kobject_get_unless_zero(&ctrl->device->kobj))
break; break;
file->private_data = ctrl; file->private_data = ctrl;
ret = 0; ret = 0;
...@@ -2374,7 +2374,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid) ...@@ -2374,7 +2374,7 @@ static void nvme_alloc_ns(struct nvme_ctrl *ctrl, unsigned nsid)
list_add_tail(&ns->list, &ctrl->namespaces); list_add_tail(&ns->list, &ctrl->namespaces);
mutex_unlock(&ctrl->namespaces_mutex); mutex_unlock(&ctrl->namespaces_mutex);
kref_get(&ctrl->kref); nvme_get_ctrl(ctrl);
kfree(id); kfree(id);
...@@ -2703,7 +2703,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl); ...@@ -2703,7 +2703,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl);
void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
{ {
device_destroy(nvme_class, MKDEV(nvme_char_major, ctrl->instance)); device_del(ctrl->device);
spin_lock(&dev_list_lock); spin_lock(&dev_list_lock);
list_del(&ctrl->node); list_del(&ctrl->node);
...@@ -2711,23 +2711,17 @@ void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) ...@@ -2711,23 +2711,17 @@ void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
} }
EXPORT_SYMBOL_GPL(nvme_uninit_ctrl); EXPORT_SYMBOL_GPL(nvme_uninit_ctrl);
static void nvme_free_ctrl(struct kref *kref) static void nvme_free_ctrl(struct device *dev)
{ {
struct nvme_ctrl *ctrl = container_of(kref, struct nvme_ctrl, kref); struct nvme_ctrl *ctrl =
container_of(dev, struct nvme_ctrl, ctrl_device);
put_device(ctrl->device);
ida_simple_remove(&nvme_instance_ida, ctrl->instance); ida_simple_remove(&nvme_instance_ida, ctrl->instance);
ida_destroy(&ctrl->ns_ida); ida_destroy(&ctrl->ns_ida);
ctrl->ops->free_ctrl(ctrl); ctrl->ops->free_ctrl(ctrl);
} }
void nvme_put_ctrl(struct nvme_ctrl *ctrl)
{
kref_put(&ctrl->kref, nvme_free_ctrl);
}
EXPORT_SYMBOL_GPL(nvme_put_ctrl);
/* /*
* Initialize a NVMe controller structures. This needs to be called during * Initialize a NVMe controller structures. This needs to be called during
* earliest initialization so that we have the initialized structured around * earliest initialization so that we have the initialized structured around
...@@ -2742,7 +2736,6 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, ...@@ -2742,7 +2736,6 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
spin_lock_init(&ctrl->lock); spin_lock_init(&ctrl->lock);
INIT_LIST_HEAD(&ctrl->namespaces); INIT_LIST_HEAD(&ctrl->namespaces);
mutex_init(&ctrl->namespaces_mutex); mutex_init(&ctrl->namespaces_mutex);
kref_init(&ctrl->kref);
ctrl->dev = dev; ctrl->dev = dev;
ctrl->ops = ops; ctrl->ops = ops;
ctrl->quirks = quirks; ctrl->quirks = quirks;
...@@ -2755,15 +2748,21 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, ...@@ -2755,15 +2748,21 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
goto out; goto out;
ctrl->instance = ret; ctrl->instance = ret;
ctrl->device = device_create_with_groups(nvme_class, ctrl->dev, device_initialize(&ctrl->ctrl_device);
MKDEV(nvme_char_major, ctrl->instance), ctrl->device = &ctrl->ctrl_device;
ctrl, nvme_dev_attr_groups, ctrl->device->devt = MKDEV(nvme_char_major, ctrl->instance);
"nvme%d", ctrl->instance); ctrl->device->class = nvme_class;
if (IS_ERR(ctrl->device)) { ctrl->device->parent = ctrl->dev;
ret = PTR_ERR(ctrl->device); ctrl->device->groups = nvme_dev_attr_groups;
ctrl->device->release = nvme_free_ctrl;
dev_set_drvdata(ctrl->device, ctrl);
ret = dev_set_name(ctrl->device, "nvme%d", ctrl->instance);
if (ret)
goto out_release_instance; goto out_release_instance;
} ret = device_add(ctrl->device);
get_device(ctrl->device); if (ret)
goto out_free_name;
ida_init(&ctrl->ns_ida); ida_init(&ctrl->ns_ida);
spin_lock(&dev_list_lock); spin_lock(&dev_list_lock);
...@@ -2779,6 +2778,8 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, ...@@ -2779,6 +2778,8 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
min(default_ps_max_latency_us, (unsigned long)S32_MAX)); min(default_ps_max_latency_us, (unsigned long)S32_MAX));
return 0; return 0;
out_free_name:
kfree_const(dev->kobj.name);
out_release_instance: out_release_instance:
ida_simple_remove(&nvme_instance_ida, ctrl->instance); ida_simple_remove(&nvme_instance_ida, ctrl->instance);
out: out:
......
...@@ -2692,14 +2692,10 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl) ...@@ -2692,14 +2692,10 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl)
struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl); struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
int ret; int ret;
if (!kref_get_unless_zero(&ctrl->ctrl.kref)) nvme_get_ctrl(&ctrl->ctrl);
return -EBUSY;
ret = __nvme_fc_del_ctrl(ctrl); ret = __nvme_fc_del_ctrl(ctrl);
if (!ret) if (!ret)
flush_workqueue(nvme_wq); flush_workqueue(nvme_wq);
nvme_put_ctrl(&ctrl->ctrl); nvme_put_ctrl(&ctrl->ctrl);
return ret; return ret;
...@@ -2918,7 +2914,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, ...@@ -2918,7 +2914,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
kref_get(&ctrl->ctrl.kref); nvme_get_ctrl(&ctrl->ctrl);
dev_info(ctrl->ctrl.device, dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: new ctrl: NQN \"%s\"\n", "NVME-FC{%d}: new ctrl: NQN \"%s\"\n",
......
...@@ -127,12 +127,12 @@ struct nvme_ctrl { ...@@ -127,12 +127,12 @@ struct nvme_ctrl {
struct request_queue *admin_q; struct request_queue *admin_q;
struct request_queue *connect_q; struct request_queue *connect_q;
struct device *dev; struct device *dev;
struct kref kref;
int instance; int instance;
struct blk_mq_tag_set *tagset; struct blk_mq_tag_set *tagset;
struct blk_mq_tag_set *admin_tagset; struct blk_mq_tag_set *admin_tagset;
struct list_head namespaces; struct list_head namespaces;
struct mutex namespaces_mutex; struct mutex namespaces_mutex;
struct device ctrl_device;
struct device *device; /* char device */ struct device *device; /* char device */
struct list_head node; struct list_head node;
struct ida ns_ida; struct ida ns_ida;
...@@ -279,6 +279,16 @@ static inline void nvme_end_request(struct request *req, __le16 status, ...@@ -279,6 +279,16 @@ static inline void nvme_end_request(struct request *req, __le16 status,
blk_mq_complete_request(req); blk_mq_complete_request(req);
} }
static inline void nvme_get_ctrl(struct nvme_ctrl *ctrl)
{
get_device(ctrl->device);
}
static inline void nvme_put_ctrl(struct nvme_ctrl *ctrl)
{
put_device(ctrl->device);
}
void nvme_complete_rq(struct request *req); void nvme_complete_rq(struct request *req);
void nvme_cancel_request(struct request *req, void *data, bool reserved); void nvme_cancel_request(struct request *req, void *data, bool reserved);
bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
......
...@@ -2292,7 +2292,7 @@ static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status) ...@@ -2292,7 +2292,7 @@ static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status)
{ {
dev_warn(dev->ctrl.device, "Removing after probe failure status: %d\n", status); dev_warn(dev->ctrl.device, "Removing after probe failure status: %d\n", status);
kref_get(&dev->ctrl.kref); nvme_get_ctrl(&dev->ctrl);
nvme_dev_disable(dev, false); nvme_dev_disable(dev, false);
if (!schedule_work(&dev->remove_work)) if (!schedule_work(&dev->remove_work))
nvme_put_ctrl(&dev->ctrl); nvme_put_ctrl(&dev->ctrl);
......
...@@ -1793,8 +1793,7 @@ static int nvme_rdma_del_ctrl(struct nvme_ctrl *nctrl) ...@@ -1793,8 +1793,7 @@ static int nvme_rdma_del_ctrl(struct nvme_ctrl *nctrl)
* Keep a reference until all work is flushed since * Keep a reference until all work is flushed since
* __nvme_rdma_del_ctrl can free the ctrl mem * __nvme_rdma_del_ctrl can free the ctrl mem
*/ */
if (!kref_get_unless_zero(&ctrl->ctrl.kref)) nvme_get_ctrl(&ctrl->ctrl);
return -EBUSY;
ret = __nvme_rdma_del_ctrl(ctrl); ret = __nvme_rdma_del_ctrl(ctrl);
if (!ret) if (!ret)
flush_work(&ctrl->delete_work); flush_work(&ctrl->delete_work);
...@@ -1955,7 +1954,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, ...@@ -1955,7 +1954,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs\n", dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs\n",
ctrl->ctrl.opts->subsysnqn, &ctrl->addr); ctrl->ctrl.opts->subsysnqn, &ctrl->addr);
kref_get(&ctrl->ctrl.kref); nvme_get_ctrl(&ctrl->ctrl);
mutex_lock(&nvme_rdma_ctrl_mutex); mutex_lock(&nvme_rdma_ctrl_mutex);
list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list); list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list);
......
...@@ -642,7 +642,7 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev, ...@@ -642,7 +642,7 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
dev_info(ctrl->ctrl.device, dev_info(ctrl->ctrl.device,
"new ctrl: \"%s\"\n", ctrl->ctrl.opts->subsysnqn); "new ctrl: \"%s\"\n", ctrl->ctrl.opts->subsysnqn);
kref_get(&ctrl->ctrl.kref); nvme_get_ctrl(&ctrl->ctrl);
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed); WARN_ON_ONCE(!changed);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment