]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
Add user parameter to specify data area region from telemetry log
authorMaxim <maximveligan@gmail.com>
Thu, 7 Jun 2018 18:06:04 +0000 (11:06 -0700)
committerKeith Busch <keith.busch@intel.com>
Fri, 8 Jun 2018 20:52:03 +0000 (14:52 -0600)
And read in block size chunks instead of 4k.

Link: https://github.com/linux-nvme/nvme-cli/pull/361
Signed-off-by: Maxim Veligan <maximveligan@gmail.com>
[changelog, formatting, set error on exit, removed unnecessary error check]
Signed-off-by: Keith Busch <keith.busch@intel.com>
nvme.c

diff --git a/nvme.c b/nvme.c
index a065e5d8e6c30a85f3ded7f9f400ef48ff6378a4..d5492eda81bdcd8fea903810b49fdbee2f512735 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -234,26 +234,31 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
        const char *fname = "File name to save raw binary, includes header";
        const char *hgen = "Have the host tell the controller to generate the report";
        const char *cgen = "Gather report generated by the controller.";
+       const char *dgen = "Pick which telemetry data area to report. Default is all. Valid options are 1, 2, 3.";
+       const size_t bs = 512;
        struct nvme_telemetry_log_page_hdr *hdr;
+       size_t full_size, offset = bs;
+       int err = 0, fd, output;
        void *page_log;
-       size_t full_size, offset, num_blocks;
-       int err = 0 , fd, output;
 
        struct config {
                char *file_name;
                __u32 host_gen;
                int ctrl_init;
+               int data_area;
        };
        struct config cfg = {
                .file_name = NULL,
                .host_gen = 1,
                .ctrl_init = 0,
+               .data_area = 3,
        };
 
        const struct argconfig_commandline_options command_line_options[] = {
-               {"output-file", 'o', "FILE", CFG_STRING, &cfg.file_name, required_argument, fname},
-               {"host-generate", 'h', "NUM", CFG_POSITIVE, &cfg.host_gen, required_argument, hgen},
-               {"controller-init", 'c', "", CFG_NONE, &cfg.ctrl_init, no_argument, cgen},
+               {"output-file",     'o', "FILE", CFG_STRING,   &cfg.file_name, required_argument, fname},
+               {"host-generate",   'h', "NUM",  CFG_POSITIVE, &cfg.host_gen,  required_argument, hgen},
+               {"controller-init", 'c', "",     CFG_NONE,     &cfg.ctrl_init, no_argument,       cgen},
+               {"data-area",       'd', "NUM",  CFG_POSITIVE, &cfg.data_area, required_argument, dgen},
                {NULL}
        };
 
@@ -275,44 +280,52 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
        }
 
        cfg.host_gen = !!cfg.host_gen;
+       hdr = malloc(bs);
+       page_log = malloc(bs);
+       if (!hdr || !page_log) {
+               fprintf(stderr, "Failed to allocate %zu bytes for log\n", bs);
+               err = ENOMEM;
+               goto free_mem;
+       }
 
-       hdr = malloc(4096);
-       memset(hdr, 0, 4096);
-
-       err = nvme_get_telemetry_log(fd, hdr, cfg.host_gen, cfg.ctrl_init, 4096, 0);
+       memset(hdr, 0, bs);
+       err = nvme_get_telemetry_log(fd, hdr, cfg.host_gen, cfg.ctrl_init, bs, 0);
        if (err) {
                fprintf(stderr, "NVMe Status:%s(%x)\n",
                        nvme_status_to_string(err), err);
                fprintf(stderr, "Failed to aquire telemetry header %d!\n", err);
-               free(hdr);
-               goto close_output;
+               close(output);
+               goto free_mem;
        }
 
-       err = write(output, (void *) hdr, 4096);
-       if (err != 4096) {
+       err = write(output, (void *) hdr, bs);
+       if (err != bs) {
                fprintf(stderr, "Failed to flush all data to file!");
-               goto free_hdr;
+               goto free_mem;
        }
 
-       num_blocks = max(hdr->dalb1, max(hdr->dalb2, hdr->dalb3));
-
-       full_size = num_blocks * 512;
-       /* Round to page boundary */
-       full_size += (4096 - (full_size % 4096));
-       /* We've already pulled 1 page worth of data, lets remove that. */
-       full_size -= 4096;
-       offset = 4096;
-
-       page_log = malloc(4096);
-       if (!page_log) {
-               fprintf(stderr, "Failed to allocate %zu bytes for log\n",
-                       full_size);
-               err = ENOMEM;
-               goto free_hdr;
+       switch (cfg.data_area) {
+       case 1:
+               full_size = (hdr->dalb1 * bs) + offset;
+               break;
+       case 2:
+               full_size = (hdr->dalb2 * bs) + offset;
+               break;
+       case 3:
+               full_size = (hdr->dalb3 * bs) + offset;
+               break;
+       default:
+               fprintf(stderr, "Invalid data area requested");
+               err = EINVAL;
+               goto free_mem;
        }
 
-       while (full_size) {
-               err = nvme_get_telemetry_log(fd, page_log, 0, cfg.ctrl_init, 4096, offset);
+       /*
+        * Continuously pull data until the offset hits the end of the last
+        * block.
+        */
+       while (offset != full_size) {
+               err = nvme_get_telemetry_log(fd, page_log, 0, cfg.ctrl_init, bs, offset);
                if (err) {
                        fprintf(stderr, "Failed to aquire full telemetry log!\n");
                        fprintf(stderr, "NVMe Status:%s(%x)\n",
@@ -320,20 +333,16 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd, struct
                        break;
                }
 
-               err = write(output, (void *) page_log, 4096);
-               if (err != 4096) {
+               err = write(output, (void *) page_log, bs);
+               if (err != bs) {
                        fprintf(stderr, "Failed to flush all data to file!");
                        break;
                }
-               full_size -= 4096;
-               offset += 4096;
+               offset += bs;
        }
-
-       free(page_log);
- free_hdr:
+ free_mem:
        free(hdr);
- close_output:
-       close(output);
+       free(page_log);
  close_fd:
        close(fd);
        return err;