Introduce a new nvme_execute_passthru_rq() helper which calls
nvme_passthru_[start|end]() around blk_execute_rq(). This ensures
all passthru calls (including nvme_submit_io()) will be wrapped
appropriately.

nvme_execute_passthru_rq() will also be useful for the nvmet passthru
code.

Signed-off-by: Logan Gunthorpe <[email protected]>
Reviewed-by: Sagi Grimberg <[email protected]>
---
 drivers/nvme/host/core.c | 193 ++++++++++++++++++++-------------------
 1 file changed, 100 insertions(+), 93 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 5062a83c3634..2ead7ad45a9d 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -890,6 +890,105 @@ static void *nvme_add_user_metadata(struct bio *bio, void 
__user *ubuf,
        return ERR_PTR(ret);
 }
 
+static u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
+                               u8 opcode)
+{
+       u32 effects = 0;
+
+       if (ns) {
+               if (ctrl->effects)
+                       effects = le32_to_cpu(ctrl->effects->iocs[opcode]);
+               if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC))
+                       dev_warn(ctrl->device,
+                                "IO command:%02x has unhandled effects:%08x\n",
+                                opcode, effects);
+               return 0;
+       }
+
+       if (ctrl->effects)
+               effects = le32_to_cpu(ctrl->effects->acs[opcode]);
+
+       switch (opcode) {
+       case nvme_admin_format_nvm:
+               effects |= NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC |
+                       NVME_CMD_EFFECTS_CSE_MASK;
+               break;
+       case nvme_admin_sanitize_nvm:
+               effects |= NVME_CMD_EFFECTS_CSE_MASK;
+               break;
+       default:
+               break;
+       }
+
+       return effects & ~NVME_CMD_EFFECTS_CSUPP;
+}
+
+static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
+                              u8 opcode)
+{
+       u32 effects = nvme_command_effects(ctrl, ns, opcode);
+
+       /*
+        * For simplicity, IO to all namespaces is quiesced even if the command
+        * effects say only one namespace is affected.
+        */
+       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
+               mutex_lock(&ctrl->scan_lock);
+               mutex_lock(&ctrl->subsys->lock);
+               nvme_mpath_start_freeze(ctrl->subsys);
+               nvme_mpath_wait_freeze(ctrl->subsys);
+               nvme_start_freeze(ctrl);
+               nvme_wait_freeze(ctrl);
+       }
+       return effects;
+}
+
+static void nvme_update_formats(struct nvme_ctrl *ctrl)
+{
+       struct nvme_ns *ns;
+
+       down_read(&ctrl->namespaces_rwsem);
+       list_for_each_entry(ns, &ctrl->namespaces, list)
+               if (ns->disk && nvme_revalidate_disk(ns->disk))
+                       nvme_set_queue_dying(ns);
+       up_read(&ctrl->namespaces_rwsem);
+}
+
+static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
+{
+       /*
+        * Revalidate LBA changes prior to unfreezing. This is necessary to
+        * prevent memory corruption if a logical block size was changed by
+        * this command.
+        */
+       if (effects & NVME_CMD_EFFECTS_LBCC)
+               nvme_update_formats(ctrl);
+       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
+               nvme_unfreeze(ctrl);
+               nvme_mpath_unfreeze(ctrl->subsys);
+               mutex_unlock(&ctrl->subsys->lock);
+               nvme_remove_invalid_namespaces(ctrl, NVME_NSID_ALL);
+               mutex_unlock(&ctrl->scan_lock);
+       }
+       if (effects & NVME_CMD_EFFECTS_CCC)
+               nvme_init_identify(ctrl);
+       if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
+               nvme_queue_scan(ctrl);
+}
+
+static void nvme_execute_passthru_rq(struct request *rq)
+{
+       struct nvme_command *cmd = nvme_req(rq)->cmd;
+       struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl;
+       struct nvme_ns *ns = rq->q->queuedata;
+       struct gendisk *disk = ns ? ns->disk : NULL;
+       u32 effects;
+
+       effects = nvme_passthru_start(ctrl, ns, cmd->common.opcode);
+       blk_execute_rq(rq->q, disk, rq, 0);
+       nvme_passthru_end(ctrl, effects);
+}
+
 static int nvme_submit_user_cmd(struct request_queue *q,
                struct nvme_command *cmd, void __user *ubuffer,
                unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
@@ -928,7 +1027,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
                }
        }
 
-       blk_execute_rq(req->q, disk, req, 0);
+       nvme_execute_passthru_rq(req);
        if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
                ret = -EINTR;
        else
@@ -1317,99 +1416,12 @@ static int nvme_submit_io(struct nvme_ns *ns, struct 
nvme_user_io __user *uio)
                        metadata, meta_len, lower_32_bits(io.slba), NULL, 0);
 }
 
-static u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-                               u8 opcode)
-{
-       u32 effects = 0;
-
-       if (ns) {
-               if (ctrl->effects)
-                       effects = le32_to_cpu(ctrl->effects->iocs[opcode]);
-               if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC))
-                       dev_warn(ctrl->device,
-                                "IO command:%02x has unhandled effects:%08x\n",
-                                opcode, effects);
-               return 0;
-       }
-
-       if (ctrl->effects)
-               effects = le32_to_cpu(ctrl->effects->acs[opcode]);
-
-       switch (opcode) {
-       case nvme_admin_format_nvm:
-               effects |= NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC |
-                       NVME_CMD_EFFECTS_CSE_MASK;
-               break;
-       case nvme_admin_sanitize_nvm:
-               effects |= NVME_CMD_EFFECTS_CSE_MASK;
-               break;
-       default:
-               break;
-       }
-
-       return effects;
-}
-
-static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
-                              u8 opcode)
-{
-       u32 effects = nvme_command_effects(ctrl, ns, opcode);
-
-       /*
-        * For simplicity, IO to all namespaces is quiesced even if the command
-        * effects say only one namespace is affected.
-        */
-       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
-               mutex_lock(&ctrl->scan_lock);
-               mutex_lock(&ctrl->subsys->lock);
-               nvme_mpath_start_freeze(ctrl->subsys);
-               nvme_mpath_wait_freeze(ctrl->subsys);
-               nvme_start_freeze(ctrl);
-               nvme_wait_freeze(ctrl);
-       }
-       return effects;
-}
-
-static void nvme_update_formats(struct nvme_ctrl *ctrl)
-{
-       struct nvme_ns *ns;
-
-       down_read(&ctrl->namespaces_rwsem);
-       list_for_each_entry(ns, &ctrl->namespaces, list)
-               if (ns->disk && nvme_revalidate_disk(ns->disk))
-                       nvme_set_queue_dying(ns);
-       up_read(&ctrl->namespaces_rwsem);
-}
-
-static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
-{
-       /*
-        * Revalidate LBA changes prior to unfreezing. This is necessary to
-        * prevent memory corruption if a logical block size was changed by
-        * this command.
-        */
-       if (effects & NVME_CMD_EFFECTS_LBCC)
-               nvme_update_formats(ctrl);
-       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
-               nvme_unfreeze(ctrl);
-               nvme_mpath_unfreeze(ctrl->subsys);
-               mutex_unlock(&ctrl->subsys->lock);
-               nvme_remove_invalid_namespaces(ctrl, NVME_NSID_ALL);
-               mutex_unlock(&ctrl->scan_lock);
-       }
-       if (effects & NVME_CMD_EFFECTS_CCC)
-               nvme_init_identify(ctrl);
-       if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
-               nvme_queue_scan(ctrl);
-}
-
 static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
                        struct nvme_passthru_cmd __user *ucmd)
 {
        struct nvme_passthru_cmd cmd;
        struct nvme_command c;
        unsigned timeout = 0;
-       u32 effects;
        u64 result;
        int status;
 
@@ -1436,12 +1448,10 @@ static int nvme_user_cmd(struct nvme_ctrl *ctrl, struct 
nvme_ns *ns,
        if (cmd.timeout_ms)
                timeout = msecs_to_jiffies(cmd.timeout_ms);
 
-       effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
        status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
                        nvme_to_user_ptr(cmd.addr), cmd.data_len,
                        nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
                        0, &result, timeout);
-       nvme_passthru_end(ctrl, effects);
 
        if (status >= 0) {
                if (put_user(result, &ucmd->result))
@@ -1457,7 +1467,6 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, struct 
nvme_ns *ns,
        struct nvme_passthru_cmd64 cmd;
        struct nvme_command c;
        unsigned timeout = 0;
-       u32 effects;
        int status;
 
        if (!capable(CAP_SYS_ADMIN))
@@ -1483,12 +1492,10 @@ static int nvme_user_cmd64(struct nvme_ctrl *ctrl, 
struct nvme_ns *ns,
        if (cmd.timeout_ms)
                timeout = msecs_to_jiffies(cmd.timeout_ms);
 
-       effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
        status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
                        nvme_to_user_ptr(cmd.addr), cmd.data_len,
                        nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
                        0, &cmd.result, timeout);
-       nvme_passthru_end(ctrl, effects);
 
        if (status >= 0) {
                if (put_user(cmd.result, &ucmd->result))
-- 
2.20.1

Reply via email to