Home Home > GIT Browse > SLE15-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLee Duncan <lduncan@suse.com>2019-09-10 10:02:16 -0700
committerLee Duncan <lduncan@suse.com>2019-09-10 10:02:16 -0700
commit1c00dbd98bd2a758324d79671454fef91bc795e3 (patch)
tree078737b28a68bc3df27bc4cf8c1484c3333b8ba3
parenta60ce2f1ac00d9f660c053b970e420fa37d47a5c (diff)
parentf93fe24dfdcca35c8f8acf0d19d8e37bc1065cc5 (diff)
Merge branch 'SLE15' into users/lduncan/SLE15/for-next
-rw-r--r--block/blk-mq.c7
-rw-r--r--drivers/nvme/host/core.c2
-rw-r--r--drivers/nvme/host/fc.c51
-rw-r--r--drivers/nvme/host/multipath.c13
-rw-r--r--include/linux/blk-mq.h2
5 files changed, 61 insertions, 14 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 15ebbbb4ca2a..1ea504b789c0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -588,6 +588,13 @@ void blk_mq_complete_request(struct request *rq)
}
EXPORT_SYMBOL(blk_mq_complete_request);
+void blk_mq_complete_request_sync(struct request *rq)
+{
+ if (!blk_mark_rq_complete(rq))
+ rq->q->mq_ops->complete(rq);
+}
+EXPORT_SYMBOL_GPL(blk_mq_complete_request_sync);
+
int blk_mq_request_started(struct request *rq)
{
return test_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 12f8f3a3eb76..9155d84e94cd 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -285,7 +285,7 @@ void nvme_cancel_request(struct request *req, void *data, bool reserved)
"Cancelling I/O %d", req->tag);
nvme_req(req)->status = NVME_SC_ABORT_REQ;
- blk_mq_complete_request(req);
+ blk_mq_complete_request_sync(req);
}
EXPORT_SYMBOL_GPL(nvme_cancel_request);
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index a1063c08212d..6ff1c0a78ea7 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -211,6 +211,9 @@ static DEFINE_IDA(nvme_fc_ctrl_cnt);
+static bool nvme_fc_waiting_to_unload;
+static DECLARE_COMPLETION(nvme_fc_unload_proceed);
+
/*
* These items are short-term. They will eventually be moved into
* a generic FC class. See comments in module init.
@@ -236,6 +239,8 @@ nvme_fc_free_lport(struct kref *ref)
/* remove from transport list */
spin_lock_irqsave(&nvme_fc_lock, flags);
list_del(&lport->port_list);
+ if (nvme_fc_waiting_to_unload && list_empty(&nvme_fc_lport_list))
+ complete(&nvme_fc_unload_proceed);
spin_unlock_irqrestore(&nvme_fc_lock, flags);
ida_simple_remove(&nvme_fc_local_port_cnt, lport->localport.port_num);
@@ -3462,11 +3467,51 @@ out_destroy_class:
return ret;
}
+static void
+nvme_fc_delete_controllers(struct nvme_fc_rport *rport)
+{
+ struct nvme_fc_ctrl *ctrl;
+
+ spin_lock(&rport->lock);
+ list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list) {
+ dev_warn(ctrl->ctrl.device,
+ "NVME-FC{%d}: transport unloading: deleting ctrl\n",
+ ctrl->cnum);
+ nvme_delete_ctrl(&ctrl->ctrl);
+ }
+ spin_unlock(&rport->lock);
+}
+
+static void
+nvme_fc_cleanup_for_unload(void)
+{
+ struct nvme_fc_lport *lport;
+ struct nvme_fc_rport *rport;
+
+ list_for_each_entry(lport, &nvme_fc_lport_list, port_list) {
+ list_for_each_entry(rport, &lport->endp_list, endp_list) {
+ nvme_fc_delete_controllers(rport);
+ }
+ }
+}
+
static void __exit nvme_fc_exit_module(void)
{
- /* sanity check - all lports should be removed */
- if (!list_empty(&nvme_fc_lport_list))
- pr_warn("%s: localport list not empty\n", __func__);
+ unsigned long flags;
+ bool need_cleanup = false;
+
+ spin_lock_irqsave(&nvme_fc_lock, flags);
+ nvme_fc_waiting_to_unload = true;
+ if (!list_empty(&nvme_fc_lport_list)) {
+ need_cleanup = true;
+ nvme_fc_cleanup_for_unload();
+ }
+ spin_unlock_irqrestore(&nvme_fc_lock, flags);
+ if (need_cleanup) {
+ pr_info("%s: waiting for ctlr deletes\n", __func__);
+ wait_for_completion(&nvme_fc_unload_proceed);
+ pr_info("%s: ctrl deletes complete\n", __func__);
+ }
nvmf_unregister_transport(&nvme_fc_transport);
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 70ae22569947..a133e22392cc 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -364,6 +364,8 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
dev->groups = nvme_ns_id_attr_groups;
device_add_disk(&head->subsys->dev, head->disk);
}
+
+ kblockd_schedule_work(&ns->head->requeue_work);
}
static int nvme_parse_ana_log(struct nvme_ctrl *ctrl, void *data,
@@ -414,19 +416,13 @@ static inline bool nvme_state_is_live(enum nvme_ana_state state)
static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc,
struct nvme_ns *ns)
{
- enum nvme_ana_state old;
-
mutex_lock(&ns->head->lock);
- old = ns->ana_state;
ns->ana_grpid = le32_to_cpu(desc->grpid);
ns->ana_state = desc->state;
clear_bit(NVME_NS_ANA_PENDING, &ns->flags);
- if (nvme_state_is_live(ns->ana_state)) {
- if (!nvme_state_is_live(old))
- nvme_mpath_set_live(ns);
- kblockd_schedule_work(&ns->head->requeue_work);
- }
+ if (nvme_state_is_live(ns->ana_state))
+ nvme_mpath_set_live(ns);
mutex_unlock(&ns->head->lock);
}
@@ -609,7 +605,6 @@ void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id)
mutex_lock(&ns->head->lock);
ns->ana_state = NVME_ANA_OPTIMIZED;
nvme_mpath_set_live(ns);
- kblockd_schedule_work(&ns->head->requeue_work);
mutex_unlock(&ns->head->lock);
}
}
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index cfd64e500d82..346f03e240be 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -237,7 +237,7 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
void blk_mq_kick_requeue_list(struct request_queue *q);
void blk_mq_delay_kick_requeue_list(struct request_queue *q, unsigned long msecs);
void blk_mq_complete_request(struct request *rq);
-
+void blk_mq_complete_request_sync(struct request *rq);
bool blk_mq_queue_stopped(struct request_queue *q);
void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx);
void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx);