nvmet: split log page implementation
authorChristoph Hellwig <hch@lst.de>
Tue, 22 May 2018 09:10:03 +0000 (11:10 +0200)
committerChristoph Hellwig <hch@lst.de>
Fri, 1 Jun 2018 12:37:35 +0000 (14:37 +0200)
Remove the common code to allocate a buffer and copy it into the SGL.
Instead the two no-op implementations just zero the SGL directly, and
the smart log allocates a buffer on its own.  This prepares for the
more elaborate ANA log page.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
drivers/nvme/target/admin-cmd.c

index b2ba95b2eef7f526fe880413ce6984bba32e1bed..e96bb02c4f2c3b7bac33121c171c9569edacf60a 100644 (file)
@@ -32,6 +32,11 @@ u32 nvmet_get_log_page_len(struct nvme_command *cmd)
        return len;
 }
 
+static void nvmet_execute_get_log_page_noop(struct nvmet_req *req)
+{
+       nvmet_req_complete(req, nvmet_zero_sgl(req, 0, req->data_len));
+}
+
 static u16 nvmet_get_smart_log_nsid(struct nvmet_req *req,
                struct nvme_smart_log *slog)
 {
@@ -97,74 +102,26 @@ static u16 nvmet_get_smart_log_all(struct nvmet_req *req,
        return NVME_SC_SUCCESS;
 }
 
-static u16 nvmet_get_smart_log(struct nvmet_req *req,
-               struct nvme_smart_log *slog)
-{
-       u16 status;
-
-       WARN_ON(req == NULL || slog == NULL);
-       if (req->cmd->get_log_page.nsid == cpu_to_le32(NVME_NSID_ALL))
-               status = nvmet_get_smart_log_all(req, slog);
-       else
-               status = nvmet_get_smart_log_nsid(req, slog);
-       return status;
-}
-
-static void nvmet_execute_get_log_page(struct nvmet_req *req)
+static void nvmet_execute_get_log_page_smart(struct nvmet_req *req)
 {
-       struct nvme_smart_log *smart_log;
-       size_t data_len = nvmet_get_log_page_len(req->cmd);
-       void *buf;
-       u16 status = 0;
+       struct nvme_smart_log *log;
+       u16 status = NVME_SC_INTERNAL;
 
-       buf = kzalloc(data_len, GFP_KERNEL);
-       if (!buf) {
-               status = NVME_SC_INTERNAL;
+       if (req->data_len != sizeof(*log))
                goto out;
-       }
 
-       switch (req->cmd->get_log_page.lid) {
-       case NVME_LOG_ERROR:
-               /*
-                * We currently never set the More bit in the status field,
-                * so all error log entries are invalid and can be zeroed out.
-                * This is called a minum viable implementation (TM) of this
-                * mandatory log page.
-                */
-               break;
-       case NVME_LOG_SMART:
-               /*
-                * XXX: fill out actual smart log
-                *
-                * We might have a hard time coming up with useful values for
-                * many of the fields, and even when we have useful data
-                * available (e.g. units or commands read/written) those aren't
-                * persistent over power loss.
-                */
-               if (data_len != sizeof(*smart_log)) {
-                       status = NVME_SC_INTERNAL;
-                       goto err;
-               }
-               smart_log = buf;
-               status = nvmet_get_smart_log(req, smart_log);
-               if (status)
-                       goto err;
-               break;
-       case NVME_LOG_FW_SLOT:
-               /*
-                * We only support a single firmware slot which always is
-                * active, so we can zero out the whole firmware slot log and
-                * still claim to fully implement this mandatory log page.
-                */
-               break;
-       default:
-               BUG();
-       }
+       log = kzalloc(sizeof(*log), GFP_KERNEL);
+       if (!log)
+               goto out;
 
-       status = nvmet_copy_to_sgl(req, 0, buf, data_len);
+       if (req->cmd->get_log_page.nsid == cpu_to_le32(NVME_NSID_ALL))
+               status = nvmet_get_smart_log_all(req, log);
+       else
+               status = nvmet_get_smart_log_nsid(req, log);
+       if (status)
+               goto out;
 
-err:
-       kfree(buf);
+       status = nvmet_copy_to_sgl(req, 0, log, sizeof(*log));
 out:
        nvmet_req_complete(req, status);
 }
@@ -566,9 +523,25 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
 
                switch (cmd->get_log_page.lid) {
                case NVME_LOG_ERROR:
+                       /*
+                        * We currently never set the More bit in the status
+                        * field, so all error log entries are invalid and can
+                        * be zeroed out.  This is called a minum viable
+                        * implementation (TM) of this mandatory log page.
+                        */
+                       req->execute = nvmet_execute_get_log_page_noop;
+                       return 0;
                case NVME_LOG_SMART:
+                       req->execute = nvmet_execute_get_log_page_smart;
+                       return 0;
                case NVME_LOG_FW_SLOT:
-                       req->execute = nvmet_execute_get_log_page;
+                       /*
+                        * We only support a single firmware slot which always
+                        * is active, so we can zero out the whole firmware slot
+                        * log and still claim to fully implement this mandatory
+                        * log page.
+                        */
+                       req->execute = nvmet_execute_get_log_page_noop;
                        return 0;
                }
                break;