]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: Support telemetry-log over nvme-mi
authorJinliang Wang <jinliangw@google.com>
Wed, 9 Nov 2022 01:22:34 +0000 (17:22 -0800)
committerDaniel Wagner <dwagner@suse.de>
Thu, 10 Nov 2022 07:43:11 +0000 (08:43 +0100)
Copy and re-write the nvme_get_telemetry_log() function, so that we
can use the existing wrappers below to get telemetry log both in-band
and over nvme-mi:

1) nvme_cli_get_log_telemetry_ctrl
2) nvme_cli_get_log_create_telemetry_host
3) nvme_cli_get_log_telemetry_host

Signed-off-by: Jinliang Wang <jinliangw@google.com>
[dwagner: return error codes directly]
Signed-off-by: Daniel Wagner <dwagner@suse.de>
nvme.c

diff --git a/nvme.c b/nvme.c
index 795ba7692ccd28d8d36e0dd5facd203fe73989dd..34af93314bc51328f71b9fe23c35b3164c9aecff 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -540,6 +540,100 @@ ret:
        return err;
 }
 
+static int get_telemetry_log_helper(struct nvme_dev *dev, bool create,
+                                   bool ctrl, struct nvme_telemetry_log **buf,
+                                   enum nvme_telemetry_da da,
+                                   size_t *size)
+{
+       static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE;
+       struct nvme_telemetry_log *telem;
+       struct nvme_id_ctrl id_ctrl;
+       void *log, *tmp;
+       int err;
+       *size = 0;
+
+       log = calloc(1, xfer);
+       if (!log)
+               return -ENOMEM;
+
+       if (ctrl) {
+               /* set rae = true so it won't clear the current telemetry log in controller */
+               err = nvme_cli_get_log_telemetry_ctrl(dev, true, 0, xfer, log);
+       } else {
+               if (create)
+                       err = nvme_cli_get_log_create_telemetry_host(dev, log);
+               else
+                       err = nvme_cli_get_log_telemetry_host(dev, 0, xfer, log);
+       }
+
+       if (err)
+               goto free;
+
+       telem = log;
+       if (ctrl && !telem->ctrlavail) {
+               *buf = log;
+               *size = xfer;
+               printf("Warning: Telemetry Controller-Initiated Data Not Available.\n");
+               return 0;
+       }
+
+       switch (da) {
+       case NVME_TELEMETRY_DA_1:
+       case NVME_TELEMETRY_DA_2:
+       case NVME_TELEMETRY_DA_3:
+               /* dalb3 >= dalb2 >= dalb1 */
+               *size = (le16_to_cpu(telem->dalb3) + 1) * xfer;
+               break;
+       case NVME_TELEMETRY_DA_4:
+               err = nvme_cli_identify_ctrl(dev, &id_ctrl);
+               if (err) {
+                       perror("identify-ctrl");
+                       goto free;
+               }
+
+               if (id_ctrl.lpa & 0x40) {
+                       *size = (le32_to_cpu(telem->dalb4) + 1) * xfer;
+               } else {
+                       fprintf(stderr, "Data area 4 unsupported, bit 6 of Log Page Attributes not set\n");
+                       err = -EINVAL;
+                       goto free;
+               }
+               break;
+       default:
+               fprintf(stderr, "Invalid data area parameter - %d\n", da);
+               err = -EINVAL;
+               goto free;
+       }
+
+       if (xfer == *size) {
+               fprintf(stderr, "ERRO: No telemetry data block\n");
+               err = -ENOENT;
+               goto free;
+       }
+
+       tmp = realloc(log, *size);
+       if (!tmp) {
+               err = -ENOMEM;
+               goto free;
+       }
+       log = tmp;
+
+       if (ctrl) {
+               err = nvme_cli_get_log_telemetry_ctrl(dev, true, 0, *size, log);
+       } else {
+               err = nvme_cli_get_log_telemetry_host(dev, 0, *size, log);
+       }
+
+       if (!err) {
+               *buf = log;
+               return 0;
+       }
+free:
+       free(log);
+       return err;
+}
+
+
 static int get_telemetry_log(int argc, char **argv, struct command *cmd,
                             struct plugin *plugin)
 {
@@ -596,18 +690,22 @@ static int get_telemetry_log(int argc, char **argv, struct command *cmd,
        }
 
        if (cfg.ctrl_init)
-               err = nvme_get_ctrl_telemetry(dev_fd(dev), true, &log,
-                                             cfg.data_area, &total_size);
+               /* Create Telemetry Host-Initiated Data = false, Controller-Initiated = true */
+               err = get_telemetry_log_helper(dev, false, true, &log,
+                                              cfg.data_area, &total_size);
        else if (cfg.host_gen)
-               err = nvme_get_new_host_telemetry(dev_fd(dev), &log,
-                                                 cfg.data_area, &total_size);
+               /* Create Telemetry Host-Initiated Data = true, Controller-Initiated = false */
+               err = get_telemetry_log_helper(dev, true, false, &log,
+                                              cfg.data_area, &total_size);
        else
-               err = nvme_get_host_telemetry(dev_fd(dev), &log,
-                                             cfg.data_area, &total_size);
+               /* Create Telemetry Host-Initiated Data = false, Controller-Initiated = false */
+               err = get_telemetry_log_helper(dev, false, false, &log,
+                                              cfg.data_area, &total_size);
 
        if (err < 0) {
                fprintf(stderr, "get-telemetry-log: %s\n",
                        nvme_strerror(errno));
+               goto close_output;
        } else if (err > 0) {
                nvme_show_status(err);
                fprintf(stderr, "Failed to acquire telemetry log %d!\n", err);