From 589986012c4b3ab68e299a2eadca18f90080113b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 14 Jul 2022 20:28:04 +0200 Subject: Merging upstream version 2.0. Signed-off-by: Daniel Baumann --- plugins/intel/intel-nvme.c | 238 ++++++++++++++++++++++++++++----------------- 1 file changed, 147 insertions(+), 91 deletions(-) (limited to 'plugins/intel/intel-nvme.c') diff --git a/plugins/intel/intel-nvme.c b/plugins/intel/intel-nvme.c index aaa40ad..80d218c 100644 --- a/plugins/intel/intel-nvme.c +++ b/plugins/intel/intel-nvme.c @@ -5,16 +5,12 @@ #include #include -#include "linux/nvme_ioctl.h" - #include "common.h" #include "nvme.h" -#include "nvme-print.h" -#include "nvme-ioctl.h" +#include "libnvme.h" #include "plugin.h" - -#include "argconfig.h" -#include "suffix.h" +#include "linux/types.h" +#include "nvme-print.h" #define CREATE_CMD #include "intel-nvme.h" @@ -351,8 +347,8 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, struct config { __u32 namespace_id; - int raw_binary; - int json; + bool raw_binary; + bool json; }; struct config cfg = { @@ -370,8 +366,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, if (fd < 0) return fd; - err = nvme_get_log(fd, cfg.namespace_id, 0xca, false, - NVME_NO_LOG_LSP, sizeof(smart_log), &smart_log); + err = nvme_get_log_simple(fd, 0xca, sizeof(smart_log), &smart_log); if (!err) { if (cfg.json) show_intel_smart_log_jsn(&smart_log, cfg.namespace_id, devicename); @@ -381,8 +376,7 @@ static int get_additional_smart_log(int argc, char **argv, struct command *cmd, d_raw((unsigned char *)&smart_log, sizeof(smart_log)); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -395,7 +389,7 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu int err, fd; struct config { - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -410,16 +404,14 @@ static int get_market_log(int argc, char **argv, struct command *cmd, struct plu if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, 0xdd, false, - NVME_NO_LOG_LSP, sizeof(log), log); + err = nvme_get_log_simple(fd, 0xdd, sizeof(log), log); if (!err) { if (!cfg.raw_binary) printf("Intel Marketing Name Log:\n%s\n", log); else d_raw((unsigned char *)&log, sizeof(log)); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -457,7 +449,7 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct const char *desc = "Get Temperature Statistics log and show it."; const char *raw = "dump output in binary format"; struct config { - int raw_binary; + bool raw_binary; }; struct config cfg = { @@ -472,16 +464,14 @@ static int get_temp_stats_log(int argc, char **argv, struct command *cmd, struct if (fd < 0) return fd; - err = nvme_get_log(fd, NVME_NSID_ALL, 0xc5, false, - NVME_NO_LOG_LSP, sizeof(stats), &stats); + err = nvme_get_log_simple(fd, 0xc5, sizeof(stats), &stats); if (!err) { if (!cfg.raw_binary) show_temp_stats(&stats); else d_raw((unsigned char *)&stats, sizeof(stats)); } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); return err; } @@ -497,10 +487,13 @@ struct __attribute__((__packed__)) optane_lat_stats { __u64 data[9]; }; -#define MEDIA_MAJOR_IDX 0 -#define MEDIA_MINOR_IDX 1 -#define MEDIA_MAX_LEN 2 -#define OPTANE_V1000_BUCKET_LEN 8 +#define MEDIA_MAJOR_IDX 0 +#define MEDIA_MINOR_IDX 1 +#define MEDIA_MAX_LEN 2 +#define OPTANE_V1000_BUCKET_LEN 8 +#define OPTANE_V1000_BUCKET_LEN 8 +#define NAND_LAT_STATS_LEN 4868 + static struct intel_lat_stats stats; static struct optane_lat_stats v1000_stats; @@ -529,7 +522,7 @@ enum FormatUnit { #define US_IN_S 1000000 #define US_IN_MS 1000 -static const enum FormatUnit get_seconds_magnitude(__u32 microseconds) +static enum FormatUnit get_seconds_magnitude(__u32 microseconds) { if (microseconds > US_IN_S) return S; @@ -539,7 +532,7 @@ static const enum FormatUnit get_seconds_magnitude(__u32 microseconds) return US; } -static const float convert_seconds(__u32 microseconds) +static float convert_seconds(__u32 microseconds) { float divisor = 1.0; @@ -567,13 +560,15 @@ enum inf_bound_type { * either of "-INF" or "+INF", respectively. */ static void set_unit_string(char *buffer, __u32 microseconds, - enum FormatUnit unit, enum inf_bound_type bound_type) + enum FormatUnit unit, + enum inf_bound_type bound_type) { + char *string; + if (bound_type != NOINF) { - snprintf(buffer, 5, "%s", bound_type ? "+INF" : "-INF"); + snprintf(buffer, BUFSIZE, "%s", bound_type ? "+INF" : "-INF"); return; } - char *string; switch (unit) { case US: @@ -589,8 +584,9 @@ static void set_unit_string(char *buffer, __u32 microseconds, string = "_s"; break; } - snprintf(buffer, 11, "%4.2f%s", - convert_seconds(microseconds), string); + + snprintf(buffer, BUFSIZE, "%4.2f%s", convert_seconds(microseconds), + string); } static void init_buffer(char *buffer, size_t size) @@ -660,12 +656,11 @@ static void show_lat_stats_linear(struct intel_lat_stats *stats, /* * For 4.0-4.5 revision. */ +#define LATENCY_STATS_V4_BASE_BITS 6 +#define LATENCY_STATS_V4_BASE_VAL (1 << LATENCY_STATS_V4_BASE_BITS) + static int lat_stats_log_scale(int i) { - static const int LATENCY_STATS_V4_BASE_BITS = 6; - static const int LATENCY_STATS_V4_BASE_VAL = ( - 1 << LATENCY_STATS_V4_BASE_BITS); - // if (i < 128) if (i < (LATENCY_STATS_V4_BASE_VAL << 1)) return i; @@ -715,8 +710,7 @@ static void json_add_bucket(struct intel_lat_stats *stats, init_buffer(buffer, BUFSIZE); - json_object_add_value_object(bucket_list, - "bucket", bucket); + json_object_array_add(bucket_list, bucket); json_object_add_value_int(bucket, "id", id); set_unit_string(buffer, lower_us, @@ -739,8 +733,7 @@ static void json_add_bucket_optane(struct json_object *bucket_list, __u32 id, init_buffer(buffer, BUFSIZE); - json_object_add_value_object(bucket_list, - "bucket", bucket); + json_object_array_add(bucket_list, bucket); json_object_add_value_int(bucket, "id", id); set_unit_string(buffer, lower_us, @@ -775,7 +768,7 @@ static void json_lat_stats_3_0(struct intel_lat_stats *stats, int write) { struct json_object *root = json_create_object(); - struct json_object *bucket_list = json_create_object(); + struct json_object *bucket_list = json_object_new_array(); lat_stats_make_json_root(root, bucket_list, write); @@ -794,7 +787,7 @@ static void json_lat_stats_4_0(struct intel_lat_stats *stats, int write) { struct json_object *root = json_create_object(); - struct json_object *bucket_list = json_create_object(); + struct json_object *bucket_list = json_object_new_array(); lat_stats_make_json_root(root, bucket_list, write); @@ -847,11 +840,11 @@ static void show_lat_stats_4_0(struct intel_lat_stats *stats) } } -static void jason_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) +static void json_lat_stats_v1000_0(struct optane_lat_stats *stats, int write) { int i; struct json_object *root = json_create_object(); - struct json_object *bucket_list = json_create_object(); + struct json_object *bucket_list = json_object_new_array(); lat_stats_make_json_root(root, bucket_list, write); @@ -951,7 +944,7 @@ static void json_lat_stats(int write) case 1000: switch (media_version[MEDIA_MINOR_IDX]) { case 0: - jason_lat_stats_v1000_0(&v1000_stats, write); + json_lat_stats_v1000_0(&v1000_stats, write); break; default: printf("Unsupported minor revision (%u.%u)\n", @@ -998,6 +991,7 @@ static void show_lat_stats(int write) case 3: case 4: case 5: + case 6: show_lat_stats_4_0(&stats); break; default: @@ -1028,6 +1022,7 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct { int err, fd; + __u8 data[NAND_LAT_STATS_LEN]; const char *desc = "Get Intel Latency Statistics log and show it."; const char *raw = "Dump output in binary format"; @@ -1035,9 +1030,9 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct const char *write = "Get write statistics (read default)"; struct config { - int raw_binary; - int json; - int write; + bool raw_binary; + bool json; + bool write; }; struct config cfg = { @@ -1054,10 +1049,15 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct if (fd < 0) return fd; - /* Query maj and minor version first */ - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(media_version), - media_version); + /* For optate, latency stats are deleted every time their LID is pulled. + * Therefore, we query the longest lat_stats log page first. + */ + err = nvme_get_log_simple(fd, cfg.write ? 0xc2 : 0xc1, + sizeof(data), &data); + + media_version[0] = (data[1] << 8) | data[0]; + media_version[1] = (data[3] << 8) | data[2]; + if (err) goto close_fd; @@ -1065,11 +1065,23 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct __u32 thresholds[OPTANE_V1000_BUCKET_LEN] = {0}; __u32 result; - err = nvme_get_feature(fd, 0, 0xf7, 0, cfg.write ? 0x1 : 0x0, 0, - sizeof(thresholds), thresholds, &result); + struct nvme_get_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = 0xf7, + .nsid = 0, + .sel = 0, + .cdw11 = cfg.write ? 0x1 : 0x0, + .uuidx = 0, + .data_len = sizeof(thresholds), + .data = thresholds, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_get_features(&args); if (err) { - fprintf(stderr, "Quering thresholds failed. NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + fprintf(stderr, "Quering thresholds failed. "); + nvme_show_status(err); goto close_fd; } @@ -1083,13 +1095,14 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct } - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(v1000_stats), - &v1000_stats); + /* Move counter values to optate stats struct which has a + * smaller size + */ + memcpy(&v1000_stats, (struct optane_lat_stats *)data, + sizeof(struct optane_lat_stats)); } else { - err = nvme_get_log(fd, NVME_NSID_ALL, cfg.write ? 0xc2 : 0xc1, - false, NVME_NO_LOG_LSP, sizeof(stats), - &stats); + memcpy(&stats, (struct intel_lat_stats *)data, + sizeof(struct intel_lat_stats)); } if (!err) { @@ -1097,11 +1110,16 @@ static int get_lat_stats_log(int argc, char **argv, struct command *cmd, struct json_lat_stats(cfg.write); else if (!cfg.raw_binary) show_lat_stats(cfg.write); - else - d_raw((unsigned char *)&stats, sizeof(stats)); + else { + if (media_version[0] == 1000) + d_raw((unsigned char *)&v1000_stats, + sizeof(v1000_stats)); + else + d_raw((unsigned char *)&stats, + sizeof(stats)); + } } else if (err > 0) - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); close_fd: close(fd); return err; @@ -1213,7 +1231,7 @@ static int read_entire_cmd(struct nvme_passthru_cmd *cmd, int total_size, dword_tfer = min(max_tfer, total_size); while (total_size > 0) { - err = nvme_submit_admin_passthru(ioctl_fd, cmd); + err = nvme_submit_admin_passthru(ioctl_fd, cmd, NULL); if (err) { fprintf(stderr, "failed on cmd.data_len %u cmd.cdw13 %u cmd.cdw12 %x cmd.cdw10 %u err %x remaining size %d\n", @@ -1478,8 +1496,7 @@ static int get_internal_log(int argc, char **argv, struct command *command, err = 0; out: if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("intel log"); err = EIO; @@ -1518,8 +1535,8 @@ static int enable_lat_stats_tracking(int argc, char **argv, }; const struct argconfig_commandline_options command_line_options[] = { - {"enable", 'e', "", CFG_NONE, &cfg.enable, no_argument, enable_desc}, - {"disable", 'd', "", CFG_NONE, &cfg.disable, no_argument, disable_desc}, + {"enable", 'e', "", CFG_FLAG, &cfg.enable, no_argument, enable_desc}, + {"disable", 'd', "", CFG_FLAG, &cfg.disable, no_argument, disable_desc}, {NULL} }; @@ -1540,10 +1557,40 @@ static int enable_lat_stats_tracking(int argc, char **argv, if (fd < 0) return fd; + + struct nvme_get_features_args args_get = { + .args_size = sizeof(args_get), + .fd = fd, + .fid = fid, + .nsid = nsid, + .sel = sel, + .cdw11 = cdw11, + .uuidx = 0, + .data_len = data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + + struct nvme_set_features_args args_set = { + .args_size = sizeof(args_set), + .fd = fd, + .fid = fid, + .nsid = nsid, + .cdw11 = option, + .cdw12 = cdw12, + .save = save, + .uuidx = 0, + .cdw15 = 0, + .data_len = data_len, + .data = buf, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + switch (option) { case None: - err = nvme_get_feature(fd, nsid, fid, sel, cdw11, 0, data_len, buf, - &result); + err = nvme_get_features(&args_get); if (!err) { printf( "Latency Statistics Tracking (FID 0x%X) is currently (%i).\n", @@ -1555,11 +1602,9 @@ static int enable_lat_stats_tracking(int argc, char **argv, break; case True: case False: - err = nvme_set_feature(fd, nsid, fid, option, cdw12, save, 0, - data_len, buf, &result); + err = nvme_set_features(&args_set); if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("Enable latency tracking"); fprintf(stderr, "Command failed while parsing.\n"); @@ -1590,12 +1635,12 @@ static int set_lat_stats_thresholds(int argc, char **argv, __u32 result; struct config { - int write; + bool write; char *bucket_thresholds; }; struct config cfg = { - .write = 0, + .write = false, .bucket_thresholds = "", }; @@ -1615,12 +1660,11 @@ static int set_lat_stats_thresholds(int argc, char **argv, * valid buckets a user is allowed to modify. Read or write doesn't * matter */ - err = nvme_get_log(fd, NVME_NSID_ALL, 0xc2, - false, NVME_NO_LOG_LSP, sizeof(media_version), - media_version); + err = nvme_get_log_simple(fd, 0xc2, + sizeof(media_version), media_version); if (err) { - fprintf(stderr, "Querying media version failed. NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + fprintf(stderr, "Querying media version failed. "); + nvme_show_status(err); goto close_fd; } @@ -1635,13 +1679,25 @@ static int set_lat_stats_thresholds(int argc, char **argv, } - err = nvme_set_feature(fd, nsid, fid, cfg.write ? 0x1 : 0x0, - cdw12, save, 0, OPTANE_V1000_BUCKET_LEN, - thresholds, &result); + struct nvme_set_features_args args = { + .args_size = sizeof(args), + .fd = fd, + .fid = fid, + .nsid = nsid, + .cdw11 = cfg.write ? 0x1 : 0x0, + .cdw12 = cdw12, + .save = save, + .uuidx = 0, + .cdw15 = 0, + .data_len = sizeof(thresholds), + .data = thresholds, + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, + .result = &result, + }; + err = nvme_set_features(&args); if (err > 0) { - fprintf(stderr, "NVMe Status:%s(%x)\n", - nvme_status_to_string(err), err); + nvme_show_status(err); } else if (err < 0) { perror("Enable latency tracking"); fprintf(stderr, "Command failed while parsing.\n"); -- cgit v1.2.3