nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Subsystems (3)
PATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Its possible for nvme_keep_alive_work() to hit an error condition after the nvme_uninit_ctrl() in __nvme_rdma_remove_ctrl(). This can lead to usage of NULL pointer in "dev_err(ctrl->device..." since device has been destroyed by nvme_uninit_ctrl().
This has been seen during continous loop of (discover, connect, IO, disconnect).
--- drivers/nvme/host/rdma.c | 1 + 1 file changed, 1 insertion(+)
drivers/nvme/host/rdma.c +1 -0
@@ -1683,6 +1683,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)static void __nvme_rdma_remove_ctrl (struct nvme_rdma_ctrl *ctrl,bool shutdown) { +nvme_stop_keep_alive (&ctrl->ctrl);nvme_uninit_ctrl (&ctrl->ctrl);if (shutdown)nvme_rdma_shutdown_ctrl (ctrl);
Signature · 1 line
1.8.3.1
PATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Quoted 7 lines · David Milburn
Its possible for
nvme_keep_alive_work()to hit an error condition after thenvme_uninit_ctrl()in__nvme_rdma_remove_ctrl(). This can lead to usage of NULL pointer in "dev_err(ctrl->device..." since device has been destroyed bynvme_uninit_ctrl().This has been seen during continous loop of (discover, connect, IO, disconnect).
Why can't we stop the keepalive work in nvme core and get rid of the stopping in fc.c as well?
Signature · 6 lines
Johannes Thumshirn Storage jthumshirn at suse.de +49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 N?rnberg GF: Felix Imend?rffer, Jane Smithard, Graham Norton HRB 21284 (AG N?rnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
PATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Hi Johannes,
Quoted 6 lines · Johannes Thumshirn
Quoted 5 lines · David Milburn
Its possible for
nvme_keep_alive_work()to hit an error condition after thenvme_uninit_ctrl()in__nvme_rdma_remove_ctrl(). This can lead to usage of NULL pointer in "dev_err(ctrl->device..." since device has been destroyed bynvme_uninit_ctrl().
Quoted 6 lines
Quoted 2 lines
This has been seen during continous loop of (discover, connect, IO, disconnect).
Why can't we stop the keepalive work in nvme core and get rid of the stopping in
fc.cas well?
Do you mean checking ctrl->device at the beginning of nvme_keep_alive_work()? And if device has been removed, nvme_stop_keep_alive() and return?
Though still looks like nvme_rdma_error_recovery_work() will want to be able to stop keep_alive, and some error handling in fc.c.
Thanks,
David
PATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Quoted 16 lines · David Milburn
Hi Johannes,
Quoted 6 lines · Johannes Thumshirn
Quoted 5 lines · David Milburn
Its possible for
nvme_keep_alive_work()to hit an error condition after thenvme_uninit_ctrl()in__nvme_rdma_remove_ctrl(). This can lead to usage of NULL pointer in "dev_err(ctrl->device..." since device has been destroyed bynvme_uninit_ctrl().Quoted 7 lines
Quoted 2 lines
This has been seen during continous loop of (discover, connect, IO, disconnect).
Why can't we stop the keepalive work in nvme core and get rid of the stopping
infc.cas well?
Quoted 7 lines
Do you mean checking
ctrl->deviceat the beginning ofnvme_keep_alive_work()? And if device has been removed,nvme_stop_keep_alive()and return?Though still looks like
nvme_rdma_error_recovery_work()will want to be able to stopkeep_alive, and some error handling infc.c.
So calling nvme_stop_keep_alive() prior to nvme_uninit_ctrl() wasn't sufficient to avoid the condition ?
It looks like rdma may have missed this on the nvme_rdma_del_ctrl_work() call, it calls nvme_uninit_ctrl() then calls nvme_stop_keep_alive().
Granted, there's a race between the stop and further teardown, but that should be manageable in the core nvme code around the workaround (e.g. called to stop while its executing, work start but see cancelled, etc).
-- james
Sagi Grimberg
maintainerPATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
In reply to David MilburnQuoted 7 lines
drivers/nvme/host/rdma.c +0
-0
drivers/nvme/host/rdma.c static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl) · line 1689
Quoted 7 lines
drivers/nvme/host/rdma.c +1
-0@@ -1683,6 +1683,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)static void __nvme_rdma_remove_ctrl (struct nvme_rdma_ctrl *ctrl,bool shutdown) { +nvme_stop_keep_alive (&ctrl->ctrl);nvme_uninit_ctrl (&ctrl->ctrl);if (shutdown)nvme_rdma_shutdown_ctrl (ctrl);
This is not the only case where we can dereference the ctrl->device after nvme_uninit_ctrl. We cancel all inflight I/O afterwards too.
The problem is that we need the first part of nvme_uninit_ctrl before we start ctrl removal (flush async and scan work and remove namespaces) but the second part should only happen when we are done with the teardown.
I think we want to split nvme_uninit_ctrl into two (and for symmetry split nvme_init_ctrl too), one part to stop ctrl inflight works and one to destroy the device.
How about the patch below?
--
[PATCH] nvme: split nvme_uninit_ctrl into stop and uninit
Usually before we teardown the controller we want to:
1. complete/cancel any ctrl inflight works
2. remove ctrl namespaces
but we do not want to destroy the controller device as we might use it for logging during the teardown stage.
This patch adds nvme_start_ctrl() which queues inflight controller works (aen, ns scan, and keep-alive if kato is set) and nvme_stop_ctrl() which cancels them and remove controller namespaces (also expose __nvme_stop_ctrl for cases where we don't want to remove namespaces i.e. resets and fabrics error recovery.
We replace all the transports code that does:
if (ctrl->ctrl.queue_count > 1) {
nvme_queue_scan(ctrl)
nvme_queue_async_events(ctrl)
}
and:
nvme_start_keep_alive(ctrl)
to:
nvme_start_ctrl()
we move nvme_uninit_ctrl to ->free_ctrl handler which makes better sense as it was initialized in probe (or crete_ctrl). and replace it with nvme_stop_ctrl (or __nvme_stop_ctrl where appropriate).
---
- This is on top of the move of queue_count to struct nvme_ctrl
drivers/nvme/host/core.c | 25 ++++++++++++++++++++++++- drivers/nvme/host/fc.c | 15 ++++----------- drivers/nvme/host/nvme.h | 3 +++ drivers/nvme/host/pci.c | 15 +++------------ drivers/nvme/host/rdma.c | 29 +++++++++-------------------- drivers/nvme/target/loop.c | 21 ++++++++------------- 6 files changed, 51 insertions(+), 57 deletions(-)
drivers/nvme/host/core.c +0 -0
@@ -2591,12 +2591,35 @@ static void nvme_release_instance(struct
nvme_ctrl *ctrl)
spin_unlock(&dev_list_lock);
}
-void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
+void __nvme_stop_ctrl(struct nvme_ctrl *ctrl)
{
+ nvme_stop_keep_alive(ctrl);
flush_work(&ctrl->async_event_work);
flush_work(&ctrl->scan_work);+}
+EXPORT_SYMBOL_GPL(__nvme_stop_ctrl);
+
+void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
+{
+ __nvme_stop_ctrl(ctrl);
nvme_remove_namespaces(ctrl);+}
+EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
+
+void nvme_start_ctrl(struct nvme_ctrl *ctrl)
+{
+ if (ctrl->kato)
+ nvme_start_keep_alive(ctrl);
+ if (ctrl->queue_count > 1) {
+ nvme_queue_scan(ctrl);
+ nvme_queue_async_events(ctrl);
+ }
+}
+EXPORT_SYMBOL_GPL(nvme_start_ctrl);
+
+void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
+{
device_destroy(nvme_class, MKDEV(nvme_char_major, ctrl->instance));
spin_lock(&dev_list_lock);drivers/nvme/host/fc.c +0 -3
@@ -2231,7 +2231,6 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) out_delete_hw_queues:nvme_fc_delete_hw_io_queues (ctrl); out_cleanup_blk_queue: -nvme_stop_keep_alive (&ctrl->ctrl);blk_cleanup_queue (ctrl->ctrl.connect_q); out_free_tag_set:blk_mq_free_tag_set (&ctrl->tag_set);
@@ -2364,8 +2363,6 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) goto out_disconnect_admin_queue; } -nvme_start_keep_alive (&ctrl->ctrl); -/* FC-NVME supports normal SGL Data Block Descriptors */ if (opts->queue_size > ctrl->ctrl.maxcmd) {
@@ -2399,17 +2396,14 @@ nvme_fc_create_association(struct nvme_fc_ctrl
*ctrl)
ctrl->ctrl.nr_reconnects = 0;
- if (ctrl->ctrl.queue_count > 1) {
+ nvme_start_ctrl(&ctrl->ctrl);
+ if (ctrl->ctrl.queue_count > 1)
nvme_start_queues(&ctrl->ctrl);- nvme_queue_scan(&ctrl->ctrl);
- nvme_queue_async_events(&ctrl->ctrl);
- }
return 0; /* Success */
out_term_aen_ops:
nvme_fc_term_aen_ops(ctrl);
- nvme_stop_keep_alive(&ctrl->ctrl);
out_disconnect_admin_queue:
/* send a Disconnect(association) LS to fc-nvme target */
nvme_fc_xmt_disconnect_assoc(ctrl);
@@ -2432,8 +2426,6 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
{
unsigned long flags;- nvme_stop_keep_alive(&ctrl->ctrl);
-
spin_lock_irqsave(&ctrl->lock, flags);
ctrl->flags |= FCCTRL_TERMIO;
ctrl->iocnt = 0;@@ -2515,7 +2507,7 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)
cancel_work_sync(&ctrl->ctrl.reset_work);
cancel_delayed_work_sync(&ctrl->connect_work);-
+ nvme_stop_ctrl(&ctrl->ctrl);
/*
* kill the association on the link side. this will block
* waiting for io to terminate
@@ -2610,6 +2602,7 @@ nvme_fc_reset_ctrl_work(struct work_struct *work)
container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
int ret;+ __nvme_stop_ctrl(&ctrl->ctrl);
/* will block will waiting for io to terminate */
nvme_fc_delete_association(ctrl);drivers/nvme/host/nvme.h +3 -0
@@ -280,6 +280,9 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl);int nvme_init_ctrl (struct nvme_ctrl *ctrl,struct device *dev,const struct nvme_ctrl_ops *ops,unsigned long quirks);void nvme_uninit_ctrl (struct nvme_ctrl *ctrl); +void nvme_start_ctrl (struct nvme_ctrl *ctrl); +void __nvme_stop_ctrl (struct nvme_ctrl *ctrl); +void nvme_stop_ctrl (struct nvme_ctrl *ctrl);void nvme_put_ctrl (struct nvme_ctrl *ctrl);int nvme_init_identify (struct nvme_ctrl *ctrl);
drivers/nvme/host/pci.c +1 -2
@@ -2048,6 +2048,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) {struct nvme_dev *dev =to_nvme_dev (ctrl); +nvme_uninit_ctrl (ctrl);nvme_dbbuf_dma_free (dev);put_device (dev->dev);if (dev->tagset.tags)
@@ -2129,15 +2130,6 @@ static void nvme_reset_work(struct work_struct *work) goto out;/* -* A controller that can not execute IO typically requires user -* intervention to correct. For such degraded controllers, the
driver
- * should not submit commands the user did not request, so skip
- * registering for asynchronous event notification on this
condition.
- */
- if (dev->online_queues > 1)
- nvme_queue_async_events(&dev->ctrl);
-
- /*
* Keep the controller around but remove all namespaces if we
don't have
* any working I/O queue.
*/
@@ -2157,8 +2149,7 @@ static void nvme_reset_work(struct work_struct *work)
goto out;
}- if (dev->online_queues > 1)
- nvme_queue_scan(&dev->ctrl);
+ nvme_start_ctrl(&dev->ctrl);
return; out:
@@ -2335,7 +2326,7 @@ static void nvme_remove(struct pci_dev *pdev)
}
flush_work(&dev->ctrl.reset_work);
- nvme_uninit_ctrl(&dev->ctrl);
+ nvme_stop_ctrl(&dev->ctrl);
nvme_dev_disable(dev, true);
nvme_free_host_mem(dev);
nvme_dev_remove_admin(dev);drivers/nvme/host/rdma.c +2 -0
@@ -664,6 +664,8 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)if (list_empty (&ctrl->list)) goto free_ctrl; +nvme_uninit_ctrl (nctrl); +mutex_lock (&nvme_rdma_ctrl_mutex);list_del (&ctrl->list);mutex_unlock (&nvme_rdma_ctrl_mutex);
@@ -731,8 +733,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct
work_struct *work)
if (ret)
goto requeue;- nvme_start_keep_alive(&ctrl->ctrl);
-
if (ctrl->ctrl.queue_count > 1) {
ret = nvme_rdma_init_io_queues(ctrl);
if (ret)
@@ -750,10 +750,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct
work_struct *work)
WARN_ON_ONCE(!changed);
ctrl->ctrl.nr_reconnects = 0;- if (ctrl->ctrl.queue_count > 1) {
- nvme_queue_scan(&ctrl->ctrl);
- nvme_queue_async_events(&ctrl->ctrl);
- }
+ nvme_start_ctrl(&ctrl->ctrl);
dev_info(ctrl->ctrl.device, "Successfully reconnected\n");
@@ -771,7 +768,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
struct nvme_rdma_ctrl, err_work);
int i;- nvme_stop_keep_alive(&ctrl->ctrl);
+ __nvme_stop_ctrl(&ctrl->ctrl);
for (i = 0; i < ctrl->ctrl.queue_count; i++)
clear_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[i].flags);
@@ -1603,8 +1600,6 @@ static int nvme_rdma_configure_admin_queue(struct
nvme_rdma_ctrl *ctrl)
if (error)
goto out_cleanup_queue;- nvme_start_keep_alive(&ctrl->ctrl);
-
return 0;
out_cleanup_queue:
@@ -1622,7 +1617,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)
static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl) {
- nvme_stop_keep_alive(&ctrl->ctrl);
cancel_work_sync(&ctrl->err_work);
cancel_delayed_work_sync(&ctrl->reconnect_work);@@ -1644,7 +1638,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)
static void __nvme_rdma_remove_ctrl(struct nvme_rdma_ctrl *ctrl, bool
shutdown)
{
- nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_stop_ctrl(&ctrl->ctrl);
if (shutdown)
nvme_rdma_shutdown_ctrl(ctrl);@@ -1709,6 +1703,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
int ret;
bool changed;+ __nvme_stop_ctrl(&ctrl->ctrl);
nvme_rdma_shutdown_ctrl(ctrl);
ret = nvme_rdma_configure_admin_queue(ctrl);
@@ -1738,11 +1733,9 @@ static void nvme_rdma_reset_ctrl_work(struct
work_struct *work)
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed);- if (ctrl->ctrl.queue_count > 1) {
+ nvme_start_ctrl(&ctrl->ctrl);
+ if (ctrl->ctrl.queue_count > 1)
nvme_start_queues(&ctrl->ctrl);- nvme_queue_scan(&ctrl->ctrl);
- nvme_queue_async_events(&ctrl->ctrl);
- }
return;
@@ -1930,15 +1923,11 @@ static struct nvme_ctrl
*nvme_rdma_create_ctrl(struct device *dev,
list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list);
mutex_unlock(&nvme_rdma_ctrl_mutex);- if (ctrl->ctrl.queue_count > 1) {
- nvme_queue_scan(&ctrl->ctrl);
- nvme_queue_async_events(&ctrl->ctrl);
- }
+ nvme_start_ctrl(&ctrl->ctrl);
return &ctrl->ctrl;
out_remove_admin_queue:
- nvme_stop_keep_alive(&ctrl->ctrl);
nvme_rdma_destroy_admin_queue(ctrl);
out_kfree_queues:
kfree(ctrl->queues);drivers/nvme/target/loop.c +2 -0
@@ -287,6 +287,8 @@ static void nvme_loop_free_ctrl(struct nvme_ctrl *nctrl)if (list_empty (&ctrl->list)) goto free_ctrl; +nvme_uninit_ctrl (nctrl); +mutex_lock (&nvme_loop_ctrl_mutex);list_del (&ctrl->list);mutex_unlock (&nvme_loop_ctrl_mutex);
@@ -407,8 +409,6 @@ static int nvme_loop_configure_admin_queue(struct
nvme_loop_ctrl *ctrl)
if (error)
goto out_cleanup_queue;- nvme_start_keep_alive(&ctrl->ctrl);
-
return 0;
out_cleanup_queue:
@@ -422,8 +422,6 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl) {
- nvme_stop_keep_alive(&ctrl->ctrl);
-
if (ctrl->ctrl.queue_count > 1) {
nvme_stop_queues(&ctrl->ctrl);
blk_mq_tagset_busy_iter(&ctrl->tag_set,@@ -445,7 +443,7 @@ static void nvme_loop_del_ctrl_work(struct work_struct *work)
struct nvme_loop_ctrl *ctrl = container_of(work,
struct nvme_loop_ctrl, delete_work);
- nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_stop_ctrl(&ctrl->ctrl);
nvme_loop_shutdown_ctrl(ctrl);
nvme_put_ctrl(&ctrl->ctrl);
}
@@ -494,6 +492,7 @@ static void nvme_loop_reset_ctrl_work(struct
work_struct *work)
bool changed;
int ret;+ __nvme_stop_ctrl(&ctrl->ctrl);
nvme_loop_shutdown_ctrl(ctrl);
ret = nvme_loop_configure_admin_queue(ctrl);
@@ -514,10 +513,9 @@ static void nvme_loop_reset_ctrl_work(struct
work_struct *work)
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed);- nvme_queue_scan(&ctrl->ctrl);
- nvme_queue_async_events(&ctrl->ctrl);
-
- nvme_start_queues(&ctrl->ctrl); + nvme_start_ctrl(&ctrl->ctrl); + if (ctrl->ctrl.queue_count > 1)
+ nvme_start_queues(&ctrl->ctrl);
return;
@@ -652,10 +650,7 @@ static struct nvme_ctrl
*nvme_loop_create_ctrl(struct device *dev,
list_add_tail(&ctrl->list, &nvme_loop_ctrl_list);
mutex_unlock(&nvme_loop_ctrl_mutex);- if (opts->nr_io_queues) {
- nvme_queue_scan(&ctrl->ctrl);
- nvme_queue_async_events(&ctrl->ctrl);
- }
+ nvme_start_ctrl(&ctrl->ctrl);
return &ctrl->ctrl;
--
Sagi Grimberg
maintainerPATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Quoted 1 line
How about the patch below?
Ping?
Quoted 425 lines
Signature · 45 lines
[PATCH] nvme: split nvme_uninit_ctrl into stop and uninit Usually before we teardown the controller we want to: 1. complete/cancel any ctrl inflight works 2. remove ctrl namespaces but we do not want to destroy the controller device as we might use it for logging during the teardown stage. This patch adds nvme_start_ctrl() which queues inflight controller works (aen, ns scan, and keep-alive if kato is set) and nvme_stop_ctrl() which cancels them and remove controller namespaces (also expose __nvme_stop_ctrl for cases where we don't want to remove namespaces i.e. resets and fabrics error recovery. We replace all the transports code that does: if (ctrl->ctrl.queue_count > 1) { nvme_queue_scan(ctrl) nvme_queue_async_events(ctrl) } and: nvme_start_keep_alive(ctrl) to: nvme_start_ctrl() we move nvme_uninit_ctrl to ->free_ctrl handler which makes better sense as it was initialized in probe (or crete_ctrl). and replace it with nvme_stop_ctrl (or __nvme_stop_ctrl where appropriate). Signed-off-by: Sagi Grimberg <sagi at grimberg.me> --- - This is on top of the move of queue_count to struct nvme_ctrl drivers/nvme/host/core.c | 25 ++++++++++++++++++++++++- drivers/nvme/host/fc.c | 15 ++++----------- drivers/nvme/host/nvme.h | 3 +++ drivers/nvme/host/pci.c | 15 +++------------ drivers/nvme/host/rdma.c | 29 +++++++++-------------------- drivers/nvme/target/loop.c | 21 ++++++++------------- 6 files changed, 51 insertions(+), 57 deletions(-)drivers/nvme/host/core.c +24
-1@@ -2591,12 +2591,35 @@ static void nvme_release_instance(struct nvme_ctrl *ctrl) spin_unlock(&dev_list_lock); } -void nvme_uninit_ctrl (struct nvme_ctrl *ctrl) +void __nvme_stop_ctrl (struct nvme_ctrl *ctrl) { +nvme_stop_keep_alive (ctrl);flush_work (&ctrl->async_event_work);flush_work (&ctrl->scan_work); +} +EXPORT_SYMBOL_GPL (__nvme_stop_ctrl); + +void nvme_stop_ctrl (struct nvme_ctrl *ctrl) +{ +__nvme_stop_ctrl (ctrl);nvme_remove_namespaces (ctrl); +} +EXPORT_SYMBOL_GPL (nvme_stop_ctrl); + +void nvme_start_ctrl (struct nvme_ctrl *ctrl) +{ +if (ctrl->kato) +nvme_start_keep_alive (ctrl); +if (ctrl->queue_count >1 ) { +nvme_queue_scan (ctrl); +nvme_queue_async_events (ctrl); + } +} +EXPORT_SYMBOL_GPL (nvme_start_ctrl); + +void nvme_uninit_ctrl (struct nvme_ctrl *ctrl) +{device_destroy (nvme_class,MKDEV (nvme_char_major, ctrl->instance));spin_lock(&dev_list_lock);drivers/nvme/host/fc.c +2
-8@@ -2231,7 +2231,6 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) out_delete_hw_queues:nvme_fc_delete_hw_io_queues (ctrl); out_cleanup_blk_queue: -nvme_stop_keep_alive (&ctrl->ctrl);blk_cleanup_queue (ctrl->ctrl.connect_q); out_free_tag_set:blk_mq_free_tag_set (&ctrl->tag_set);@@ -2364,8 +2363,6 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) goto out_disconnect_admin_queue; } -nvme_start_keep_alive (&ctrl->ctrl); -/* FC-NVME supports normal SGL Data Block Descriptors */ if (opts->queue_size > ctrl->ctrl.maxcmd) {@@ -2399,17 +2396,14 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) ctrl->ctrl.nr_reconnects =0 ; -if (ctrl->ctrl.queue_count >1 ) { +nvme_start_ctrl (&ctrl->ctrl); +if (ctrl->ctrl.queue_count >1 )nvme_start_queues (&ctrl->ctrl); -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - }return 0 ;/* Success */ out_term_aen_ops:nvme_fc_term_aen_ops (ctrl); -nvme_stop_keep_alive (&ctrl->ctrl); out_disconnect_admin_queue:/* send a Disconnect(association) LS to fc-nvme target */ nvme_fc_xmt_disconnect_assoc(ctrl);drivers/nvme/host/fc.c +2
-3@@ -2432,8 +2426,6 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) {unsigned long flags; -nvme_stop_keep_alive (&ctrl->ctrl); -spin_lock_irqsave (&ctrl->lock, flags); ctrl->flags |=FCCTRL_TERMIO ; ctrl->iocnt =0 ;@@ -2515,7 +2507,7 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)cancel_work_sync (&ctrl->ctrl.reset_work);cancel_delayed_work_sync (&ctrl->connect_work); - +nvme_stop_ctrl (&ctrl->ctrl);/* * kill the association on the link side. this will block * waiting for io to terminate @@ -2610,6 +2602,7 @@ nvme_fc_reset_ctrl_work(struct work_struct *work) container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);int ret; +__nvme_stop_ctrl (&ctrl->ctrl);/* will block will waiting for io to terminate */ nvme_fc_delete_association (ctrl);drivers/nvme/host/nvme.h +3
-0@@ -280,6 +280,9 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl);int nvme_init_ctrl (struct nvme_ctrl *ctrl,struct device *dev,const struct nvme_ctrl_ops *ops,unsigned long quirks);void nvme_uninit_ctrl (struct nvme_ctrl *ctrl); +void nvme_start_ctrl (struct nvme_ctrl *ctrl); +void __nvme_stop_ctrl (struct nvme_ctrl *ctrl); +void nvme_stop_ctrl (struct nvme_ctrl *ctrl);void nvme_put_ctrl (struct nvme_ctrl *ctrl);int nvme_init_identify (struct nvme_ctrl *ctrl);drivers/nvme/host/pci.c +1
-0@@ -2048,6 +2048,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) {struct nvme_dev *dev =to_nvme_dev (ctrl); +nvme_uninit_ctrl (ctrl);nvme_dbbuf_dma_free (dev);put_device (dev->dev);if (dev->tagset.tags)drivers/nvme/host/pci.c +0
-2@@ -2129,15 +2130,6 @@ static void nvme_reset_work(struct work_struct *work) goto out;/* -* A controller that can not execute IO typically requires user -* intervention to correct. For such degraded controllers, the driver
drivers/nvme/host/pci.c +0
-2-* should not submit commands the user did not request, so skip -* registering for asynchronous event notification on this condition.
drivers/nvme/host/pci.c +0
-5-*/ -if (dev->online_queues >1 ) -nvme_queue_async_events (&dev->ctrl); - -/* * Keep the controller around but remove all namespaces if we don't have
* any working I/O queue.
*/drivers/nvme/host/pci.c +2
-3@@ -2157,8 +2149,7 @@ static void nvme_reset_work(struct work_struct *work) goto out; } -if (dev->online_queues >1 ) -nvme_queue_scan (&dev->ctrl); +nvme_start_ctrl (&dev->ctrl);return ; out:@@ -2335,7 +2326,7 @@ static void nvme_remove(struct pci_dev *pdev) }flush_work (&dev->ctrl.reset_work); -nvme_uninit_ctrl (&dev->ctrl); +nvme_stop_ctrl (&dev->ctrl);nvme_dev_disable (dev, true);nvme_free_host_mem (dev);nvme_dev_remove_admin (dev);drivers/nvme/host/rdma.c +2
-0@@ -664,6 +664,8 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)if (list_empty (&ctrl->list)) goto free_ctrl; +nvme_uninit_ctrl (nctrl); +mutex_lock (&nvme_rdma_ctrl_mutex);list_del (&ctrl->list);mutex_unlock(&nvme_rdma_ctrl_mutex);drivers/nvme/host/rdma.c +0
-2@@ -731,8 +733,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)if (ret) goto requeue; -nvme_start_keep_alive (&ctrl->ctrl); -if (ctrl->ctrl.queue_count >1 ) { ret =nvme_rdma_init_io_queues (ctrl);if (ret)
drivers/nvme/host/rdma.c +2
-5@@ -750,10 +750,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) WARN_ON_ONCE(!changed); ctrl->ctrl.nr_reconnects =0 ; -if (ctrl->ctrl.queue_count >1 ) { -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - } +nvme_start_ctrl (&ctrl->ctrl);dev_info (ctrl->ctrl.device,"Successfully reconnected\n" );@@ -771,7 +768,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work) struct nvme_rdma_ctrl, err_work);int i; -nvme_stop_keep_alive (&ctrl->ctrl); +__nvme_stop_ctrl (&ctrl->ctrl);for (i =0 ; i < ctrl->ctrl.queue_count; i++)clear_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[i].flags);drivers/nvme/host/rdma.c +0
-2@@ -1603,8 +1600,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)if (error) goto out_cleanup_queue; -nvme_start_keep_alive (&ctrl->ctrl); -return 0 ;
out_cleanup_queue:drivers/nvme/host/rdma.c +1
-2@@ -1622,7 +1617,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)static void nvme_rdma_shutdown_ctrl (struct nvme_rdma_ctrl *ctrl) { -nvme_stop_keep_alive (&ctrl->ctrl);cancel_work_sync (&ctrl->err_work);cancel_delayed_work_sync (&ctrl->reconnect_work);@@ -1644,7 +1638,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)static void __nvme_rdma_remove_ctrl (struct nvme_rdma_ctrl *ctrl,bool shutdown) { -nvme_uninit_ctrl (&ctrl->ctrl); +nvme_stop_ctrl (&ctrl->ctrl);if (shutdown)nvme_rdma_shutdown_ctrl(ctrl);drivers/nvme/host/rdma.c +1
-0@@ -1709,6 +1703,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)int ret;bool changed; +__nvme_stop_ctrl (&ctrl->ctrl);nvme_rdma_shutdown_ctrl (ctrl);ret = nvme_rdma_configure_admin_queue(ctrl);drivers/nvme/host/rdma.c +3
-9@@ -1738,11 +1733,9 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work) changed =nvme_change_ctrl_state (&ctrl->ctrl,NVME_CTRL_LIVE );WARN_ON_ONCE (!changed); -if (ctrl->ctrl.queue_count >1 ) { +nvme_start_ctrl (&ctrl->ctrl); +if (ctrl->ctrl.queue_count >1 )nvme_start_queues (&ctrl->ctrl); -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - }return ;@@ -1930,15 +1923,11 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list);mutex_unlock (&nvme_rdma_ctrl_mutex); -if (ctrl->ctrl.queue_count >1 ) { -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - } +nvme_start_ctrl (&ctrl->ctrl);return &ctrl->ctrl; out_remove_admin_queue: -nvme_stop_keep_alive (&ctrl->ctrl);nvme_rdma_destroy_admin_queue (ctrl); out_kfree_queues:kfree(ctrl->queues);drivers/nvme/target/loop.c +2
-0@@ -287,6 +287,8 @@ static void nvme_loop_free_ctrl(struct nvme_ctrl *nctrl)if (list_empty (&ctrl->list)) goto free_ctrl; +nvme_uninit_ctrl (nctrl); +mutex_lock (&nvme_loop_ctrl_mutex);list_del (&ctrl->list);mutex_unlock(&nvme_loop_ctrl_mutex);drivers/nvme/target/loop.c +0
-2@@ -407,8 +409,6 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)if (error) goto out_cleanup_queue; -nvme_start_keep_alive (&ctrl->ctrl); -return 0 ;
out_cleanup_queue:drivers/nvme/target/loop.c +0
-2@@ -422,8 +422,6 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)static void nvme_loop_shutdown_ctrl (struct nvme_loop_ctrl *ctrl) { -nvme_stop_keep_alive (&ctrl->ctrl); -if (ctrl->ctrl.queue_count >1 ) {nvme_stop_queues (&ctrl->ctrl);blk_mq_tagset_busy_iter(&ctrl->tag_set,drivers/nvme/target/loop.c +1
-1@@ -445,7 +443,7 @@ static void nvme_loop_del_ctrl_work(struct work_struct *work)struct nvme_loop_ctrl *ctrl =container_of (work, struct nvme_loop_ctrl, delete_work); -nvme_uninit_ctrl (&ctrl->ctrl); +nvme_stop_ctrl (&ctrl->ctrl);nvme_loop_shutdown_ctrl (ctrl);nvme_put_ctrl (&ctrl->ctrl);}drivers/nvme/target/loop.c +1
-0@@ -494,6 +492,7 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)bool changed;int ret; +__nvme_stop_ctrl (&ctrl->ctrl);nvme_loop_shutdown_ctrl (ctrl);ret = nvme_loop_configure_admin_queue(ctrl);drivers/nvme/target/loop.c +4
-8@@ -514,10 +513,9 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work) changed =nvme_change_ctrl_state (&ctrl->ctrl,NVME_CTRL_LIVE );WARN_ON_ONCE (!changed); -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - -nvme_start_queues (&ctrl->ctrl); +nvme_start_ctrl (&ctrl->ctrl); +if (ctrl->ctrl.queue_count >1 ) +nvme_start_queues (&ctrl->ctrl);return ;@@ -652,10 +650,7 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev, list_add_tail(&ctrl->list, &nvme_loop_ctrl_list);mutex_unlock (&nvme_loop_ctrl_mutex); -if (opts->nr_io_queues) { -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - } +nvme_start_ctrl (&ctrl->ctrl);return &ctrl->ctrl;Signature · 1 line
--
Christoph Hellwig
maintainerPATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
In reply to Sagi GrimbergThis idea looks fine - please send it out in a separate thread.
A few minor comments below:
Review
Quoted 8 lines
(quoted diff) +4
-1-void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) +void __nvme_stop_ctrl(struct nvme_ctrl *ctrl) { + nvme_stop_keep_alive(ctrl); flush_work(&ctrl->async_event_work); flush_work(&ctrl->scan_work); +} +EXPORT_SYMBOL_GPL(__nvme_stop_ctrl);
I don't really like the __nvme_stop_ctrl name for something that is called all the time. I think this should be nvme_stop_ctrl.
Review
Quoted 7 lines
(quoted diff) +6
-0+ +void nvme_stop_ctrl(struct nvme_ctrl *ctrl) +{ + __nvme_stop_ctrl(ctrl); nvme_remove_namespaces(ctrl); +} +EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
And then this becomes nvme_remove_ctrl?
Review
Quoted 3 lines
(quoted diff) +2
-0+ nvme_start_ctrl(&ctrl->ctrl); + if (ctrl->ctrl.queue_count > 1) nvme_start_queues(&ctrl->ctrl);
Maybe add a nvme_restart_ctrl for this always duplicated sequence?
Sagi Grimberg
maintainerPATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Quoted 1 line
This idea looks fine - please send it out in a separate thread.
Will do
Quoted 13 lines
A few minor comments below:
Review
Quoted 8 lines
(quoted diff) +4
-1-void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) +void __nvme_stop_ctrl(struct nvme_ctrl *ctrl) { + nvme_stop_keep_alive(ctrl); flush_work(&ctrl->async_event_work); flush_work(&ctrl->scan_work); +} +EXPORT_SYMBOL_GPL(__nvme_stop_ctrl);I don't really like the
__nvme_stop_ctrlname for something that is called all the time. I think this should benvme_stop_ctrl.
Fine by me.
Quoted 9 lines
Review
Quoted 7 lines
(quoted diff) +6
-0+ +void nvme_stop_ctrl(struct nvme_ctrl *ctrl) +{ + __nvme_stop_ctrl(ctrl); nvme_remove_namespaces(ctrl); +} +EXPORT_SYMBOL_GPL(nvme_stop_ctrl);And then this becomes
nvme_remove_ctrl?
Not a good idea as its not actually removing the controller...
Maybe nvme_clear_ctrl?
Quoted 5 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ nvme_start_ctrl(&ctrl->ctrl); + if (ctrl->ctrl.queue_count > 1) nvme_start_queues(&ctrl->ctrl);Maybe add a
nvme_restart_ctrlfor this always duplicated sequence?
sounds like an idea..
Christoph Hellwig
maintainerPATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Quoted 9 lines · Sagi Grimberg
Quoted 8 lines
Review
Quoted 6 lines
(quoted diff) +5
-0+void nvme_stop_ctrl(struct nvme_ctrl *ctrl) +{ + __nvme_stop_ctrl(ctrl); nvme_remove_namespaces(ctrl); +} +EXPORT_SYMBOL_GPL(nvme_stop_ctrl);And then this becomes
nvme_remove_ctrl?
Quoted 3 lines
Not a good idea as its not actually removing the controller...
Maybe
nvme_clear_ctrl?
Or just call both the new nvme_stop_ctrl and nvme_remove_namespaces from each driver. It's a bit more code, but additional logic..
Sagi Grimberg
maintainerPATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Review
Quoted 7 lines
(quoted diff) +5
-0+void nvme_stop_ctrl(struct nvme_ctrl *ctrl) +{ + __nvme_stop_ctrl(ctrl); nvme_remove_namespaces(ctrl); +} +EXPORT_SYMBOL_GPL(nvme_stop_ctrl);And then this becomes
nvme_remove_ctrl?
Quoted 6 lines
Quoted 3 lines
Not a good idea as its not actually removing the controller...
Maybe
nvme_clear_ctrl?Or just call both the new
nvme_stop_ctrlandnvme_remove_namespacesfrom each driver. It's a bit more code, but additional logic..
Yea... I hope we can get it centralize soon so it won't be duplicated.
btw, I think I can unconditionally call nvme_start_queues in nvme_start_ctrl, the extra unquiesce won't hurt. In fact, pci does it today. probe calls reset which unconditionally starts the queues...
PATCH 1/1 nvme-rdma: stop keep_alive before nvme_uninit_ctrl
In reply to Sagi GrimbergHi Sagi,
Quoted 24 lines · Sagi Grimberg
Quoted 13 lines
drivers/nvme/host/rdma.c +1
-0@@ -1683,6 +1683,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)static void __nvme_rdma_remove_ctrl (struct nvme_rdma_ctrl *ctrl,bool shutdown) { +nvme_stop_keep_alive (&ctrl->ctrl);nvme_uninit_ctrl (&ctrl->ctrl);if (shutdown)Quoted 2 lines
nvme_rdma_shutdown_ctrl(ctrl);This is not the only case where we can dereference the
ctrl->deviceafternvme_uninit_ctrl. We cancel all inflight I/O afterwards too.The problem is that we need the first part of
nvme_uninit_ctrlbefore we start ctrl removal (flush async and scan work and remove namespaces) but the second part should only happen when we are done with the teardown.
Quoted 5 lines
I think we want to split
nvme_uninit_ctrlinto two (and for symmetry splitnvme_init_ctrltoo), one part to stop ctrl inflight works and one to destroy the device.How about the patch below?
Yi successfully re-tested the rdma changes.
Sorry for the delay,
David
Quoted 432 lines
Signature · 46 lines
-- [PATCH] nvme: split nvme_uninit_ctrl into stop and uninit Usually before we teardown the controller we want to: 1. complete/cancel any ctrl inflight works 2. remove ctrl namespaces but we do not want to destroy the controller device as we might use it for logging during the teardown stage. This patch adds nvme_start_ctrl() which queues inflight controller works (aen, ns scan, and keep-alive if kato is set) and nvme_stop_ctrl() which cancels them and remove controller namespaces (also expose __nvme_stop_ctrl for cases where we don't want to remove namespaces i.e. resets and fabrics error recovery. We replace all the transports code that does: if (ctrl->ctrl.queue_count > 1) { nvme_queue_scan(ctrl) nvme_queue_async_events(ctrl) } and: nvme_start_keep_alive(ctrl) to: nvme_start_ctrl() we move nvme_uninit_ctrl to ->free_ctrl handler which makes better sense as it was initialized in probe (or crete_ctrl). and replace it with nvme_stop_ctrl (or __nvme_stop_ctrl where appropriate). Signed-off-by: Sagi Grimberg <sagi at grimberg.me> --- - This is on top of the move of queue_count to struct nvme_ctrl drivers/nvme/host/core.c | 25 ++++++++++++++++++++++++- drivers/nvme/host/fc.c | 15 ++++----------- drivers/nvme/host/nvme.h | 3 +++ drivers/nvme/host/pci.c | 15 +++------------ drivers/nvme/host/rdma.c | 29 +++++++++-------------------- drivers/nvme/target/loop.c | 21 ++++++++------------- 6 files changed, 51 insertions(+), 57 deletions(-)drivers/nvme/host/core.c +24
-1@@ -2591,12 +2591,35 @@ static void nvme_release_instance(struct nvme_ctrl *ctrl) spin_unlock(&dev_list_lock); } -void nvme_uninit_ctrl (struct nvme_ctrl *ctrl) +void __nvme_stop_ctrl (struct nvme_ctrl *ctrl) { +nvme_stop_keep_alive (ctrl);flush_work (&ctrl->async_event_work);flush_work (&ctrl->scan_work); +} +EXPORT_SYMBOL_GPL (__nvme_stop_ctrl); + +void nvme_stop_ctrl (struct nvme_ctrl *ctrl) +{ +__nvme_stop_ctrl (ctrl);nvme_remove_namespaces (ctrl); +} +EXPORT_SYMBOL_GPL (nvme_stop_ctrl); + +void nvme_start_ctrl (struct nvme_ctrl *ctrl) +{ +if (ctrl->kato) +nvme_start_keep_alive (ctrl); +if (ctrl->queue_count >1 ) { +nvme_queue_scan (ctrl); +nvme_queue_async_events (ctrl); + } +} +EXPORT_SYMBOL_GPL (nvme_start_ctrl); + +void nvme_uninit_ctrl (struct nvme_ctrl *ctrl) +{device_destroy (nvme_class,MKDEV (nvme_char_major, ctrl->instance));spin_lock(&dev_list_lock);drivers/nvme/host/fc.c +2
-8@@ -2231,7 +2231,6 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl) out_delete_hw_queues:nvme_fc_delete_hw_io_queues (ctrl); out_cleanup_blk_queue: -nvme_stop_keep_alive (&ctrl->ctrl);blk_cleanup_queue (ctrl->ctrl.connect_q); out_free_tag_set:blk_mq_free_tag_set (&ctrl->tag_set);@@ -2364,8 +2363,6 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) goto out_disconnect_admin_queue; } -nvme_start_keep_alive (&ctrl->ctrl); -/* FC-NVME supports normal SGL Data Block Descriptors */ if (opts->queue_size > ctrl->ctrl.maxcmd) {@@ -2399,17 +2396,14 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) ctrl->ctrl.nr_reconnects =0 ; -if (ctrl->ctrl.queue_count >1 ) { +nvme_start_ctrl (&ctrl->ctrl); +if (ctrl->ctrl.queue_count >1 )nvme_start_queues (&ctrl->ctrl); -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - }return 0 ;/* Success */ out_term_aen_ops:nvme_fc_term_aen_ops (ctrl); -nvme_stop_keep_alive (&ctrl->ctrl); out_disconnect_admin_queue:/* send a Disconnect(association) LS to fc-nvme target */ nvme_fc_xmt_disconnect_assoc(ctrl);drivers/nvme/host/fc.c +2
-3@@ -2432,8 +2426,6 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) {unsigned long flags; -nvme_stop_keep_alive (&ctrl->ctrl); -spin_lock_irqsave (&ctrl->lock, flags); ctrl->flags |=FCCTRL_TERMIO ; ctrl->iocnt =0 ;@@ -2515,7 +2507,7 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)cancel_work_sync (&ctrl->ctrl.reset_work);cancel_delayed_work_sync (&ctrl->connect_work); - +nvme_stop_ctrl (&ctrl->ctrl);/* * kill the association on the link side. this will block * waiting for io to terminate @@ -2610,6 +2602,7 @@ nvme_fc_reset_ctrl_work(struct work_struct *work) container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);int ret; +__nvme_stop_ctrl (&ctrl->ctrl);/* will block will waiting for io to terminate */ nvme_fc_delete_association (ctrl);drivers/nvme/host/nvme.h +3
-0@@ -280,6 +280,9 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl);int nvme_init_ctrl (struct nvme_ctrl *ctrl,struct device *dev,const struct nvme_ctrl_ops *ops,unsigned long quirks);void nvme_uninit_ctrl (struct nvme_ctrl *ctrl); +void nvme_start_ctrl (struct nvme_ctrl *ctrl); +void __nvme_stop_ctrl (struct nvme_ctrl *ctrl); +void nvme_stop_ctrl (struct nvme_ctrl *ctrl);void nvme_put_ctrl (struct nvme_ctrl *ctrl);int nvme_init_identify (struct nvme_ctrl *ctrl);drivers/nvme/host/pci.c +1
-0@@ -2048,6 +2048,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl) {struct nvme_dev *dev =to_nvme_dev (ctrl); +nvme_uninit_ctrl (ctrl);nvme_dbbuf_dma_free (dev);put_device (dev->dev);if (dev->tagset.tags)drivers/nvme/host/pci.c +0
-2@@ -2129,15 +2130,6 @@ static void nvme_reset_work(struct work_struct *work) goto out;/* -* A controller that can not execute IO typically requires user -* intervention to correct. For such degraded controllers, the driver
drivers/nvme/host/pci.c +0
-2-* should not submit commands the user did not request, so skip -* registering for asynchronous event notification on this condition.
drivers/nvme/host/pci.c +0
-5-*/ -if (dev->online_queues >1 ) -nvme_queue_async_events (&dev->ctrl); - -/* * Keep the controller around but remove all namespaces if we don't have
* any working I/O queue.
*/drivers/nvme/host/pci.c +2
-3@@ -2157,8 +2149,7 @@ static void nvme_reset_work(struct work_struct *work) goto out; } -if (dev->online_queues >1 ) -nvme_queue_scan (&dev->ctrl); +nvme_start_ctrl (&dev->ctrl);return ; out:@@ -2335,7 +2326,7 @@ static void nvme_remove(struct pci_dev *pdev) }flush_work (&dev->ctrl.reset_work); -nvme_uninit_ctrl (&dev->ctrl); +nvme_stop_ctrl (&dev->ctrl);nvme_dev_disable (dev, true);nvme_free_host_mem (dev);nvme_dev_remove_admin (dev);drivers/nvme/host/rdma.c +2
-0@@ -664,6 +664,8 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)if (list_empty (&ctrl->list)) goto free_ctrl; +nvme_uninit_ctrl (nctrl); +mutex_lock (&nvme_rdma_ctrl_mutex);list_del (&ctrl->list);mutex_unlock(&nvme_rdma_ctrl_mutex);drivers/nvme/host/rdma.c +0
-2@@ -731,8 +733,6 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)if (ret) goto requeue; -nvme_start_keep_alive (&ctrl->ctrl); -if (ctrl->ctrl.queue_count >1 ) { ret =nvme_rdma_init_io_queues (ctrl);if (ret)
drivers/nvme/host/rdma.c +2
-5@@ -750,10 +750,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) WARN_ON_ONCE(!changed); ctrl->ctrl.nr_reconnects =0 ; -if (ctrl->ctrl.queue_count >1 ) { -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - } +nvme_start_ctrl (&ctrl->ctrl);dev_info (ctrl->ctrl.device,"Successfully reconnected\n" );@@ -771,7 +768,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work) struct nvme_rdma_ctrl, err_work);int i; -nvme_stop_keep_alive (&ctrl->ctrl); +__nvme_stop_ctrl (&ctrl->ctrl);for (i =0 ; i < ctrl->ctrl.queue_count; i++)clear_bit(NVME_RDMA_Q_LIVE, &ctrl->queues[i].flags);drivers/nvme/host/rdma.c +0
-2@@ -1603,8 +1600,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)if (error) goto out_cleanup_queue; -nvme_start_keep_alive (&ctrl->ctrl); -return 0 ;
out_cleanup_queue:drivers/nvme/host/rdma.c +1
-2@@ -1622,7 +1617,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl)static void nvme_rdma_shutdown_ctrl (struct nvme_rdma_ctrl *ctrl) { -nvme_stop_keep_alive (&ctrl->ctrl);cancel_work_sync (&ctrl->err_work);cancel_delayed_work_sync (&ctrl->reconnect_work);@@ -1644,7 +1638,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)static void __nvme_rdma_remove_ctrl (struct nvme_rdma_ctrl *ctrl,bool shutdown) { -nvme_uninit_ctrl (&ctrl->ctrl); +nvme_stop_ctrl (&ctrl->ctrl);if (shutdown)nvme_rdma_shutdown_ctrl(ctrl);drivers/nvme/host/rdma.c +1
-0@@ -1709,6 +1703,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)int ret;bool changed; +__nvme_stop_ctrl (&ctrl->ctrl);nvme_rdma_shutdown_ctrl (ctrl);ret = nvme_rdma_configure_admin_queue(ctrl);drivers/nvme/host/rdma.c +3
-9@@ -1738,11 +1733,9 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work) changed =nvme_change_ctrl_state (&ctrl->ctrl,NVME_CTRL_LIVE );WARN_ON_ONCE (!changed); -if (ctrl->ctrl.queue_count >1 ) { +nvme_start_ctrl (&ctrl->ctrl); +if (ctrl->ctrl.queue_count >1 )nvme_start_queues (&ctrl->ctrl); -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - }return ;@@ -1930,15 +1923,11 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev, list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list);mutex_unlock (&nvme_rdma_ctrl_mutex); -if (ctrl->ctrl.queue_count >1 ) { -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - } +nvme_start_ctrl (&ctrl->ctrl);return &ctrl->ctrl; out_remove_admin_queue: -nvme_stop_keep_alive (&ctrl->ctrl);nvme_rdma_destroy_admin_queue (ctrl); out_kfree_queues:kfree(ctrl->queues);drivers/nvme/target/loop.c +2
-0@@ -287,6 +287,8 @@ static void nvme_loop_free_ctrl(struct nvme_ctrl *nctrl)if (list_empty (&ctrl->list)) goto free_ctrl; +nvme_uninit_ctrl (nctrl); +mutex_lock (&nvme_loop_ctrl_mutex);list_del (&ctrl->list);mutex_unlock(&nvme_loop_ctrl_mutex);drivers/nvme/target/loop.c +0
-2@@ -407,8 +409,6 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)if (error) goto out_cleanup_queue; -nvme_start_keep_alive (&ctrl->ctrl); -return 0 ;
out_cleanup_queue:drivers/nvme/target/loop.c +0
-2@@ -422,8 +422,6 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)static void nvme_loop_shutdown_ctrl (struct nvme_loop_ctrl *ctrl) { -nvme_stop_keep_alive (&ctrl->ctrl); -if (ctrl->ctrl.queue_count >1 ) {nvme_stop_queues (&ctrl->ctrl);blk_mq_tagset_busy_iter(&ctrl->tag_set,drivers/nvme/target/loop.c +1
-1@@ -445,7 +443,7 @@ static void nvme_loop_del_ctrl_work(struct work_struct *work)struct nvme_loop_ctrl *ctrl =container_of (work, struct nvme_loop_ctrl, delete_work); -nvme_uninit_ctrl (&ctrl->ctrl); +nvme_stop_ctrl (&ctrl->ctrl);nvme_loop_shutdown_ctrl (ctrl);nvme_put_ctrl (&ctrl->ctrl);}drivers/nvme/target/loop.c +1
-0@@ -494,6 +492,7 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)bool changed;int ret; +__nvme_stop_ctrl (&ctrl->ctrl);nvme_loop_shutdown_ctrl (ctrl);ret = nvme_loop_configure_admin_queue(ctrl);drivers/nvme/target/loop.c +4
-8@@ -514,10 +513,9 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work) changed =nvme_change_ctrl_state (&ctrl->ctrl,NVME_CTRL_LIVE );WARN_ON_ONCE (!changed); -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - -nvme_start_queues (&ctrl->ctrl); +nvme_start_ctrl (&ctrl->ctrl); +if (ctrl->ctrl.queue_count >1 ) +nvme_start_queues (&ctrl->ctrl);return ;@@ -652,10 +650,7 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev, list_add_tail(&ctrl->list, &nvme_loop_ctrl_list);mutex_unlock (&nvme_loop_ctrl_mutex); -if (opts->nr_io_queues) { -nvme_queue_scan (&ctrl->ctrl); -nvme_queue_async_events (&ctrl->ctrl); - } +nvme_start_ctrl (&ctrl->ctrl);return &ctrl->ctrl;Signature · 6 lines
-- _______________________________________________ Linux-nvme mailing list Linux-nvme at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-nvme