}
}
-void show_nvme_resv_report(struct nvme_reservation_status *status)
+void show_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11)
{
- int i, regctl;
+ int i, j, regctl, entries;
regctl = status->regctl[0] | (status->regctl[1] << 8);
printf("\nNVME Reservation status:\n\n");
printf("gen : %d\n", le32_to_cpu(status->gen));
- printf("regctl : %d\n", regctl);
printf("rtype : %d\n", status->rtype);
+ printf("regctl : %d\n", regctl);
printf("ptpls : %d\n", status->ptpls);
- for (i = 0; i < regctl; i++) {
- printf("regctl[%d] :\n", i);
- printf(" cntlid : %x\n", le16_to_cpu(status->regctl_ds[i].cntlid));
- printf(" rcsts : %x\n", status->regctl_ds[i].rcsts);
- printf(" hostid : %"PRIx64"\n", (uint64_t)le64_to_cpu(status->regctl_ds[i].hostid));
- printf(" rkey : %"PRIx64"\n", (uint64_t)le64_to_cpu(status->regctl_ds[i].rkey));
+ /* check Extended Data Structure bit */
+ if ((cdw11 & 0x1) == 0) {
+ /* if status buffer was too small, don't loop past the end of the buffer */
+ entries = (bytes - 24) / 24;
+ if (entries < regctl)
+ regctl = entries;
+
+ for (i = 0; i < regctl; i++) {
+ printf("regctl[%d] :\n", i);
+ printf(" cntlid : %x\n", le16_to_cpu(status->regctl_ds[i].cntlid));
+ printf(" rcsts : %x\n", status->regctl_ds[i].rcsts);
+ printf(" hostid : %"PRIx64"\n", (uint64_t)le64_to_cpu(status->regctl_ds[i].hostid));
+ printf(" rkey : %"PRIx64"\n", (uint64_t)le64_to_cpu(status->regctl_ds[i].rkey));
+ }
+ } else {
+ struct nvme_reservation_status_ext *ext_status = (struct nvme_reservation_status_ext *)status;
+ /* if status buffer was too small, don't loop past the end of the buffer */
+ entries = (bytes - 64) / 64;
+ if (entries < regctl)
+ regctl = entries;
+
+ for (i = 0; i < regctl; i++) {
+ printf("regctlext[%d] :\n", i);
+ printf(" cntlid : %x\n", le16_to_cpu(ext_status->regctl_eds[i].cntlid));
+ printf(" rcsts : %x\n", ext_status->regctl_eds[i].rcsts);
+ printf(" rkey : %"PRIx64"\n", (uint64_t)le64_to_cpu(ext_status->regctl_eds[i].rkey));
+ printf(" hostid : ");
+ for (j = 0; j < 16; j++)
+ printf("%x", ext_status->regctl_eds[i].hostid[j]);
+ printf("\n");
+ }
}
printf("\n");
}
-
static char *fw_to_string(__u64 fw)
{
static char ret[9];
json_free_object(root);
}
-void json_nvme_resv_report(struct nvme_reservation_status *status)
+void json_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11)
{
struct json_object *root;
struct json_array *rcs;
- int i, regctl;
+ int i, j, regctl, entries;
regctl = status->regctl[0] | (status->regctl[1] << 8);
root = json_create_object();
json_object_add_value_int(root, "gen", le32_to_cpu(status->gen));
- json_object_add_value_int(root, "regctl", regctl);
json_object_add_value_int(root, "rtype", status->rtype);
+ json_object_add_value_int(root, "regctl", regctl);
json_object_add_value_int(root, "ptpls", status->ptpls);
rcs = json_create_array();
- json_object_add_value_array(root, "regctls", rcs);
+ /* check Extended Data Structure bit */
+ if ((cdw11 & 0x1) == 0) {
+ /* if status buffer was too small, don't loop past the end of the buffer */
+ entries = (bytes - 24) / 24;
+ if (entries < regctl)
+ regctl = entries;
+
+ json_object_add_value_array(root, "regctls", rcs);
+ for (i = 0; i < regctl; i++) {
+ struct json_object *rc = json_create_object();
+
+ json_object_add_value_int(rc, "cntlid", le16_to_cpu(status->regctl_ds[i].cntlid));
+ json_object_add_value_int(rc, "rcsts", status->regctl_ds[i].rcsts);
+ json_object_add_value_int(rc, "hostid", (uint64_t)le64_to_cpu(status->regctl_ds[i].hostid));
+ json_object_add_value_int(rc, "rkey", (uint64_t)le64_to_cpu(status->regctl_ds[i].rkey));
+
+ json_array_add_value_object(rcs, rc);
+ }
+ } else {
+ struct nvme_reservation_status_ext *ext_status = (struct nvme_reservation_status_ext *)status;
+ char hostid[33];
- for (i = 0; i < regctl; i++) {
- struct json_object *rc = json_create_object();
+ /* if status buffer was too small, don't loop past the end of the buffer */
+ entries = (bytes - 64) / 64;
+ if (entries < regctl)
+ regctl = entries;
- json_object_add_value_int(rc, "cntlid", le16_to_cpu(status->regctl_ds[i].cntlid));
- json_object_add_value_int(rc, "rcsts", status->regctl_ds[i].rcsts);
- json_object_add_value_int(rc, "hostid", (uint64_t)le64_to_cpu(status->regctl_ds[i].hostid));
- json_object_add_value_int(rc, "rkey", (uint64_t)le64_to_cpu(status->regctl_ds[i].rkey));
+ json_object_add_value_array(root, "regctlext", rcs);
+ for (i = 0; i < regctl; i++) {
+ struct json_object *rc = json_create_object();
- json_array_add_value_object(rcs, rc);
+ json_object_add_value_int(rc, "cntlid", le16_to_cpu(ext_status->regctl_eds[i].cntlid));
+ json_object_add_value_int(rc, "rcsts", ext_status->regctl_eds[i].rcsts);
+ json_object_add_value_int(rc, "rkey", (uint64_t)le64_to_cpu(ext_status->regctl_eds[i].rkey));
+ for (j = 0; j < 16; j++)
+ sprintf(hostid + j * 2, "%02x", ext_status->regctl_eds[i].hostid[j]);
+
+ json_object_add_value_string(rc, "hostid", hostid);
+
+ json_array_add_value_object(rcs, rc);
+ }
}
json_print_object(root, NULL);
void __show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root));
void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode);
void show_nvme_id_ns(struct nvme_id_ns *ns, unsigned int flags);
-void show_nvme_resv_report(struct nvme_reservation_status *status);
+void show_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11);
void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges);
void show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname);
void show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname);
void json_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, unsigned int mode, void (*vendor_show)(__u8 *vs, struct json_object *root));
void json_nvme_id_ns(struct nvme_id_ns *ns, unsigned int flags);
-void json_nvme_resv_report(struct nvme_reservation_status *status);
+void json_nvme_resv_report(struct nvme_reservation_status *status, int bytes, __u32 cdw11);
void json_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname);
void json_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname);
void json_fw_log(struct nvme_firmware_log_page *fw_log, const char *devname);
"namespace.";
const char *namespace_id = "identifier of desired namespace";
const char *numd = "number of dwords to transfer";
+ const char *cdw11 = "command dword 11 value";
const char *raw_binary = "dump output in binary format";
int err, fmt, fd;
struct config {
__u32 namespace_id;
__u32 numd;
+ __u32 cdw11;
int raw_binary;
char *output_format;
};
struct config cfg = {
.namespace_id = 0,
.numd = 0,
+ .cdw11 = 0,
.output_format = "normal",
};
const struct argconfig_commandline_options command_line_options[] = {
{"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id},
{"numd", 'd', "NUM", CFG_POSITIVE, &cfg.numd, required_argument, numd},
+ {"cdw11", 'c', "NUM", CFG_POSITIVE, &cfg.cdw11, required_argument, cdw11},
{"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary},
{"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format },
{NULL}
cfg.namespace_id = get_nsid(fd);
if (!cfg.numd || cfg.numd > (0x1000 >> 2))
cfg.numd = 0x1000 >> 2;
+ if (cfg.numd < 3)
+ cfg.numd = 3; /* get the header fields at least */
if (posix_memalign((void **)&status, getpagesize(), cfg.numd << 2)) {
fprintf(stderr, "No memory for resv report:%d\n", cfg.numd << 2);
return ENOMEM;
}
+ memset(status, 0, cfg.numd << 2);
- err = nvme_resv_report(fd, cfg.namespace_id, cfg.numd, status);
+ err = nvme_resv_report(fd, cfg.namespace_id, cfg.numd, cfg.cdw11, status);
if (err < 0)
perror("reservation report");
else if (err != 0)
if (fmt == BINARY)
d_raw((unsigned char *)status, cfg.numd << 2);
else if (fmt == JSON)
- json_nvme_resv_report(status);
+ json_nvme_resv_report(status, cfg.numd << 2, cfg.cdw11);
else {
printf("NVME Reservation Report success\n");
- show_nvme_resv_report(status);
+ show_nvme_resv_report(status, cfg.numd << 2, cfg.cdw11);
}
}
free(status);