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",
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 "\
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,
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;
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);
}