return -EINVAL;
}
+ if (*size == NVME_LOG_TELEM_BLOCK_SIZE) {
+ fprintf(stderr, "ERROR: No telemetry data block\n");
+ return -ENOENT;
+ }
return 0;
}
-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 int get_log_telemetry_ctrl(struct nvme_dev *dev, size_t size,
+ struct nvme_telemetry_log **buf)
{
- static const __u32 xfer = NVME_LOG_TELEM_BLOCK_SIZE;
- struct nvme_telemetry_log *telem;
- void *log, *tmp;
+ struct nvme_telemetry_log *log;
int err;
- *size = 0;
- log = calloc(1, xfer);
+ log = calloc(1, size);
if (!log)
- return -ENOMEM;
+ return -errno;
- 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);
+ err = nvme_cli_get_log_telemetry_ctrl(dev, true, 0, size, log);
+ if (err) {
+ free(log);
+ return -errno;
+ }
+
+ *buf = log;
+ return 0;
+}
+
+static int get_log_telemetry_host(struct nvme_dev *dev, size_t size,
+ struct nvme_telemetry_log **buf)
+{
+ struct nvme_telemetry_log *log;
+ int err;
+
+ log = calloc(1, size);
+ if (!log)
+ return -errno;
+
+ err = nvme_cli_get_log_telemetry_host(dev, 0, size, log);
+ if (err) {
+ free(log);
+ return -errno;
}
+ *buf = log;
+ return 0;
+}
+
+static int __create_telemetry_log_host(struct nvme_dev *dev,
+ enum nvme_telemetry_da da,
+ size_t *size,
+ struct nvme_telemetry_log **buf)
+{
+ struct nvme_telemetry_log log = { 0 };
+ int err;
+
+ err = nvme_cli_get_log_create_telemetry_host(dev, &log);
+ if (err)
+ return -errno;
+
+ *size = NVME_LOG_TELEM_BLOCK_SIZE;
+ return get_log_telemetry_host(dev, NVME_LOG_TELEM_BLOCK_SIZE, buf);
+}
+
+static int __get_telemetry_log_ctrl(struct nvme_dev *dev,
+ enum nvme_telemetry_da da,
+ size_t *size,
+ struct nvme_telemetry_log **buf)
+{
+ struct nvme_telemetry_log *log;
+ int err;
+
+ log = calloc(1, NVME_LOG_TELEM_BLOCK_SIZE);
+ if (!log)
+ return -errno;
+
+ /*
+ * set rae = true so it won't clear the current telemetry log in
+ * controller
+ */
+ err = nvme_cli_get_log_telemetry_ctrl(dev, true, 0,
+ NVME_LOG_TELEM_BLOCK_SIZE,
+ log);
if (err)
goto free;
- telem = log;
- if (ctrl && !telem->ctrlavail) {
+ if (!log->ctrlavail) {
+ *size = NVME_LOG_TELEM_BLOCK_SIZE;
*buf = log;
- *size = xfer;
+
printf("Warning: Telemetry Controller-Initiated Data Not Available.\n");
return 0;
}
- err = parse_telemetry_da(dev, da, telem, size);
+ err = parse_telemetry_da(dev, da, log, size);
if (err)
goto free;
- if (xfer == *size) {
- fprintf(stderr, "ERROR: No telemetry data block\n");
- err = -ENOENT;
- goto free;
- }
+ return get_log_telemetry_ctrl(dev, *size, buf);
- 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_host(struct nvme_dev *dev,
+ enum nvme_telemetry_da da,
+ size_t *size,
+ struct nvme_telemetry_log **buf)
+{
+ struct nvme_telemetry_log log = { 0 };
+ int err;
+
+ err = nvme_cli_get_log_telemetry_host(dev, 0,
+ NVME_LOG_TELEM_BLOCK_SIZE,
+ &log);
+ if (err)
+ return err;
+
+ err = parse_telemetry_da(dev, da, &log, size);
+ if (err)
+ return err;
+
+ return get_log_telemetry_host(dev, *size, buf);
+}
static int get_telemetry_log(int argc, char **argv, struct command *cmd,
struct plugin *plugin)
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 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4.";
- struct nvme_telemetry_log *log;
+ struct nvme_telemetry_log *log = NULL;
int err = 0, output;
size_t total_size;
__u8 *data_ptr = NULL;
}
if (cfg.ctrl_init)
- /* Create Telemetry Host-Initiated Data = false, Controller-Initiated = true */
- err = get_telemetry_log_helper(dev, false, true, &log,
- cfg.data_area, &total_size);
+ err = __get_telemetry_log_ctrl(dev, cfg.data_area,
+ &total_size, &log);
else if (cfg.host_gen)
- /* Create Telemetry Host-Initiated Data = true, Controller-Initiated = false */
- err = get_telemetry_log_helper(dev, true, false, &log,
- cfg.data_area, &total_size);
+ err = __create_telemetry_log_host(dev, cfg.data_area,
+ &total_size, &log);
else
- /* Create Telemetry Host-Initiated Data = false, Controller-Initiated = false */
- err = get_telemetry_log_helper(dev, false, false, &log,
- cfg.data_area, &total_size);
+ err = __get_telemetry_log_host(dev, cfg.data_area,
+ &total_size, &log);
if (err < 0) {
fprintf(stderr, "get-telemetry-log: %s\n",