[PATCH 4/9] nvmet: refactor passthru fixup code
Christoph Hellwig
hch at lst.de
Wed Dec 14 08:13:42 PST 2022
Add a helper to check if a given command needs a fixup and use that
instead of setting the use_workqueue flag that can get out of sync.
Also move the fixup into a separate out of line function.
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
drivers/nvme/target/nvmet.h | 1 -
drivers/nvme/target/passthru.c | 50 ++++++++++++++++++++++------------
2 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 89bedfcd974c41..b4f7d2aa869142 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -369,7 +369,6 @@ struct nvmet_req {
struct bio inline_bio;
struct request *rq;
struct work_struct work;
- bool use_workqueue;
} p;
#ifdef CONFIG_BLK_DEV_ZONED
struct {
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 0b238fce2c11f2..63fe8aaf968486 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -211,19 +211,20 @@ static u16 nvmet_passthru_override_id_ns(struct nvmet_req *req)
return status;
}
-static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
+static bool nvmet_passthru_needs_fixup(struct nvmet_req *req)
{
- struct nvmet_req *req = container_of(w, struct nvmet_req, p.work);
- struct request *rq = req->p.rq;
- struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl;
- struct nvme_ns *ns = rq->q->queuedata;
- u32 effects;
- int status;
+ /*
+ * Some CNS values of Identify need fixups after I/O completion and
+ * thus need to be handled in a workqueue. Don't bother selecting the
+ * specific ones as Identify performance doesn't matter too much.
+ */
+ return req->cmd->common.opcode == nvme_admin_identify;
+}
- effects = nvme_passthru_start(ctrl, ns, req->cmd->common.opcode);
- status = nvme_execute_rq(rq, false);
- if (status == NVME_SC_SUCCESS &&
- req->cmd->common.opcode == nvme_admin_identify) {
+static void nvmet_passthru_fixup(struct nvmet_req *req)
+{
+ switch (req->cmd->common.opcode) {
+ case nvme_admin_identify:
switch (req->cmd->identify.cns) {
case NVME_ID_CNS_CTRL:
nvmet_passthru_override_id_ctrl(req);
@@ -234,8 +235,26 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
case NVME_ID_CNS_NS_DESC_LIST:
nvmet_passthru_override_id_descs(req);
break;
+ default:
+ break;
}
- } else if (status < 0)
+ }
+}
+
+static void nvmet_passthru_execute_cmd_work(struct work_struct *w)
+{
+ struct nvmet_req *req = container_of(w, struct nvmet_req, p.work);
+ struct request *rq = req->p.rq;
+ struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl;
+ struct nvme_ns *ns = rq->q->queuedata;
+ u32 effects;
+ int status;
+
+ effects = nvme_passthru_start(ctrl, ns, req->cmd->common.opcode);
+ status = nvme_execute_rq(rq, false);
+ if (status == NVME_SC_SUCCESS && nvmet_passthru_needs_fixup(req))
+ nvmet_passthru_fixup(req);
+ else if (status < 0)
status = NVME_SC_INTERNAL;
req->cqe->result = nvme_req(rq)->result;
@@ -342,7 +361,7 @@ static void nvmet_passthru_execute_cmd(struct nvmet_req *req)
* which is typically in interrupt context.
*/
effects = nvme_command_effects(ctrl, ns, req->cmd->common.opcode);
- if (req->p.use_workqueue || effects) {
+ if (nvmet_passthru_needs_fixup(req) || effects) {
INIT_WORK(&req->p.work, nvmet_passthru_execute_cmd_work);
req->p.rq = rq;
queue_work(nvmet_wq, &req->p.work);
@@ -404,7 +423,6 @@ static void nvmet_passthru_set_host_behaviour(struct nvmet_req *req)
static u16 nvmet_setup_passthru_command(struct nvmet_req *req)
{
- req->p.use_workqueue = false;
req->execute = nvmet_passthru_execute_cmd;
return NVME_SC_SUCCESS;
}
@@ -538,25 +556,21 @@ u16 nvmet_parse_passthru_admin_cmd(struct nvmet_req *req)
switch (req->cmd->identify.cns) {
case NVME_ID_CNS_CTRL:
req->execute = nvmet_passthru_execute_cmd;
- req->p.use_workqueue = true;
return NVME_SC_SUCCESS;
case NVME_ID_CNS_CS_CTRL:
switch (req->cmd->identify.csi) {
case NVME_CSI_ZNS:
req->execute = nvmet_passthru_execute_cmd;
- req->p.use_workqueue = true;
return NVME_SC_SUCCESS;
}
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
case NVME_ID_CNS_NS:
req->execute = nvmet_passthru_execute_cmd;
- req->p.use_workqueue = true;
return NVME_SC_SUCCESS;
case NVME_ID_CNS_CS_NS:
switch (req->cmd->identify.csi) {
case NVME_CSI_ZNS:
req->execute = nvmet_passthru_execute_cmd;
- req->p.use_workqueue = true;
return NVME_SC_SUCCESS;
}
return NVME_SC_INVALID_OPCODE | NVME_SC_DNR;
--
2.35.1
More information about the Linux-nvme
mailing list