]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: add select 1000b to get feature changed from default
authorTokunori Ikegami <ikegami.t@gmail.com>
Sun, 23 May 2021 10:15:15 +0000 (19:15 +0900)
committerTokunori Ikegami <ikegami.t@gmail.com>
Wed, 27 Oct 2021 13:24:19 +0000 (22:24 +0900)
Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
nvme-print.c
nvme.c

index cb7a26752c634e8bf26b38191a97584789cd16e2..e662c59af3355a427aa386f8465130865570960e 100644 (file)
@@ -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 3f061184f2ab5b797654d37d295499b03841ad42..c0ab34735ca9c98f93bef0ddea7b86f863c7e445 100644 (file)
--- 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);
 }