From 30b89e5ef8971234db0c3c57c6ab761f13c3fd4f Mon Sep 17 00:00:00 2001 From: Tokunori Ikegami Date: Sun, 23 May 2021 19:15:15 +0900 Subject: [PATCH] nvme: add select 1000b to get feature changed from default Signed-off-by: Tokunori Ikegami --- nvme-print.c | 1 + nvme.c | 117 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 82 insertions(+), 36 deletions(-) diff --git a/nvme-print.c b/nvme-print.c index cb7a2675..e662c59a 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -5284,6 +5284,7 @@ const char *nvme_select_to_string(int sel) case 1: return "Default"; case 2: return "Saved"; case 3: return "Supported capabilities"; + case 8: return "Changed"; default: return "Reserved"; } } diff --git a/nvme.c b/nvme.c index 3f061184..c0ab3473 100644 --- a/nvme.c +++ b/nvme.c @@ -2714,33 +2714,35 @@ ret: return nvme_status_to_errno(err, false); } -static int get_feature_id(int fd, struct feat_cfg cfg) +static int get_feature_id(int fd, struct feat_cfg *cfg, void **buf, + __u32 *result) { - int err; - __u32 result; - void *buf = NULL; - - nvme_get_feature_length(cfg.feature_id, cfg.cdw11, &cfg.data_len); + nvme_get_feature_length(cfg->feature_id, cfg->cdw11, &cfg->data_len); /* check for Extended Host Identifier */ - if (cfg.feature_id == NVME_FEAT_FID_HOST_ID && (cfg.cdw11 & 0x1)) - cfg.data_len = 16; + if (cfg->feature_id == NVME_FEAT_FID_HOST_ID && (cfg->cdw11 & 0x1)) + cfg->data_len = 16; - if (cfg.sel == 3) - cfg.data_len = 0; + if (cfg->sel == 3) + cfg->data_len = 0; - if (cfg.data_len) { - if (posix_memalign(&buf, getpagesize(), cfg.data_len)) { + if (cfg->data_len) { + if (posix_memalign(buf, getpagesize(), cfg->data_len)) { fprintf(stderr, "can not allocate feature payload\n"); errno = ENOMEM; return -1; } - memset(buf, 0, cfg.data_len); + memset(*buf, 0, cfg->data_len); } - err = nvme_get_features(fd, cfg.feature_id, cfg.namespace_id, cfg.sel, - cfg.cdw11, cfg.uuid_index, cfg.data_len, buf, - &result); + return nvme_get_features(fd, cfg->feature_id, cfg->namespace_id, + cfg->sel, cfg->cdw11, cfg->uuid_index, + cfg->data_len, *buf, result); +} + +static void get_feature_id_print(struct feat_cfg cfg, int err, __u32 result, + void *buf) +{ if (!err) { if (!cfg.raw_binary || !buf) { printf("get-feature:%#0*x (%s), %s value:%#0*x\n", @@ -2755,21 +2757,78 @@ static int get_feature_id(int fd, struct feat_cfg cfg) buf); else if (buf) d(buf, cfg.data_len, 16, 1); - } else if (buf) + } else if (buf) { d_raw(buf, cfg.data_len); + } } else if (err > 0) { if (err != NVME_SC_INVALID_FIELD) nvme_show_status(err); } else { perror("get-feature"); } +} + +static int get_feature_id_changed(int fd, struct feat_cfg cfg, bool changed) +{ + int err; + int err_def = 0; + __u32 result; + __u32 result_def; + void *buf = NULL; + void *buf_def = NULL; + + if (changed) + cfg.sel = 0; + + err = get_feature_id(fd, &cfg, &buf, &result); + + if (!err && changed) { + cfg.sel = 1; + err_def = get_feature_id(fd, &cfg, &buf_def, &result_def); + } + + if (changed) + cfg.sel = 8; + + if (err || !changed || err_def || result != result_def || + (buf && buf_def && !strcmp(buf, buf_def))) + get_feature_id_print(cfg, err, result, buf); free(buf); + free(buf_def); return err; } -static int get_feature(int argc, char **argv, struct command *cmd, struct plugin *plugin) +static int get_feature_ids(int fd, struct feat_cfg cfg) +{ + int err = 0; + int i; + int feat_max = 0x100; + int feat_num = 0; + bool changed = false; + + if (cfg.sel == 8) + changed = true; + + if (cfg.feature_id) + feat_max = cfg.feature_id + 1; + + for (i = cfg.feature_id; i < feat_max; i++, feat_num++) { + cfg.feature_id = i; + err = get_feature_id_changed(fd, cfg, changed); + if (err && err != NVME_SC_INVALID_FIELD) + break; + } + + if (err == NVME_SC_INVALID_FIELD && feat_num == 1) + nvme_show_status(err); + + return err; +} + +static int get_feature(int argc, char **argv, struct command *cmd, + struct plugin *plugin) { const char *desc = "Read operating parameters of the "\ "specified controller. Operating parameters are grouped "\ @@ -2783,16 +2842,13 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin const char *raw = "show feature in binary format"; const char *feature_id = "feature identifier"; const char *namespace_id = "identifier of desired namespace"; - const char *sel = "[0-3]: current/default/saved/supported"; + const char *sel = "[0-3,8]: current/default/saved/supported/changed"; const char *data_len = "buffer len if data is returned through host memory buffer"; const char *cdw11 = "dword 11 for interrupt vector config"; const char *human_readable = "show feature in readable format"; const char *uuid_index = "specify uuid index"; int err; int fd; - int i; - int feat_max = 0x100; - int feat_num = 0; struct feat_cfg cfg = { .feature_id = 0, @@ -2826,20 +2882,16 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin perror("get-namespace-id"); goto close_fd; } - cfg.namespace_id = NVME_NSID_ALL; } } - if (cfg.sel > 7) { + if (cfg.sel > 8) { fprintf(stderr, "invalid 'select' param:%d\n", cfg.sel); err = -EINVAL; goto close_fd; } - if (cfg.feature_id) - feat_max = cfg.feature_id + 1; - if (cfg.uuid_index > 128) { fprintf(stderr, "invalid uuid index param: %u\n", cfg.uuid_index); errno = EINVAL; @@ -2847,18 +2899,11 @@ static int get_feature(int argc, char **argv, struct command *cmd, struct plugin goto close_fd; } - for (i = cfg.feature_id; i < feat_max; i++, feat_num++) { - cfg.feature_id = i; - err = get_feature_id(fd, cfg); - if (err && err != NVME_SC_INVALID_FIELD) - break; - } - - if (err == NVME_SC_INVALID_FIELD && feat_num == 1) - nvme_show_status(err); + err = get_feature_ids(fd, cfg); close_fd: close(fd); + ret: return nvme_status_to_errno(err, false); } -- 2.49.0