diff --git a/libnvme/src/nvme/ioctl.h b/libnvme/src/nvme/ioctl.h index a2420dd868..7181ea7b78 100644 --- a/libnvme/src/nvme/ioctl.h +++ b/libnvme/src/nvme/ioctl.h @@ -4393,9 +4393,9 @@ static inline int nvme_flush(struct nvme_transport_handle *hdl, __u32 nsid) * @cmd: Passthru command to use * @nsid: Namespace identifier * @nr: Number of block ranges in the data set management attributes - * @idr: DSM Deallocate attribute - * @idw: DSM Integral Dataset for Read attribute - * @ad: DSM Integral Dataset for Read attribute + * @idr: DSM Integral Dataset for Read attribute + * @idw: DSM Integral Dataset for Write attribute + * @ad: DSM Deallocate attribute * @data: User space destination address to transfer the data * @len: Length of provided user buffer to hold the log data in bytes */ @@ -4410,7 +4410,7 @@ nvme_init_dsm(struct nvme_passthru_cmd *cmd, cmd->nsid = nsid; cmd->data_len = len; cmd->addr = (__u64)(uintptr_t)data; - cmd->cdw10 = NVME_FIELD_ENCODE(nr, + cmd->cdw10 = NVME_FIELD_ENCODE(nr - 1, NVME_DSM_CDW10_NR_SHIFT, NVME_DSM_CDW10_NR_MASK); cmd->cdw11 = NVME_FIELD_ENCODE(idr, diff --git a/libnvme/test/ioctl/misc.c b/libnvme/test/ioctl/misc.c index 135c8f350c..3c8571460c 100644 --- a/libnvme/test/ioctl/misc.c +++ b/libnvme/test/ioctl/misc.c @@ -989,7 +989,7 @@ static void test_dsm(void) arbitrary(dsm, dsm_size); set_mock_io_cmds(&mock_io_cmd, 1); - nvme_init_dsm(&cmd, TEST_NSID, nr_ranges - 1, 0, 0, 1, dsm, dsm_size); + nvme_init_dsm(&cmd, TEST_NSID, nr_ranges, 0, 0, 1, dsm, dsm_size); err = nvme_submit_io_passthru(test_hdl, &cmd, &result); end_mock_cmds(); check(err == 0, "returned error %d", err); diff --git a/nvme.c b/nvme.c index 64c343f95e..d396b72203 100644 --- a/nvme.c +++ b/nvme.c @@ -7299,12 +7299,12 @@ static int dsm(int argc, char **argv, struct command *acmd, struct plugin *plugi _cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL; _cleanup_free_ struct nvme_dsm_range *dsm = NULL; struct nvme_passthru_cmd cmd; - uint16_t nr, nc, nb, ns; __u32 ctx_attrs[256] = {0,}; __u32 nlbs[256] = {0,}; __u64 slbas[256] = {0,}; - int err; nvme_print_flags_t flags; + uint16_t nc, nb, ns; + int err; struct config { __u32 namespace_id; @@ -7351,8 +7351,11 @@ static int dsm(int argc, char **argv, struct command *acmd, struct plugin *plugi nc = argconfig_parse_comma_sep_array_u32(cfg.ctx_attrs, ctx_attrs, ARRAY_SIZE(ctx_attrs)); nb = argconfig_parse_comma_sep_array_u32(cfg.blocks, nlbs, ARRAY_SIZE(nlbs)); ns = argconfig_parse_comma_sep_array_u64(cfg.slbas, slbas, ARRAY_SIZE(slbas)); - nr = max(nc, max(nb, ns)); - if (!nr || nr > 256) { + if (nc != nb || nb != ns) { + nvme_show_error("No valid range definition provided"); + return -EINVAL; + } + if (!nc || nc > 256) { nvme_show_error("No range definition provided"); return -EINVAL; } @@ -7364,15 +7367,19 @@ static int dsm(int argc, char **argv, struct command *acmd, struct plugin *plugi return err; } } - if (!cfg.cdw11) - cfg.cdw11 = (cfg.ad << 2) | (cfg.idw << 1) | (cfg.idr << 0); + if (cfg.cdw11) { + cfg.ad = NVME_GET(cfg.cdw11, DSM_CDW11_AD); + cfg.idw = NVME_GET(cfg.cdw11, DSM_CDW11_IDW); + cfg.idr = NVME_GET(cfg.cdw11, DSM_CDW11_IDR); + } - dsm = nvme_alloc(sizeof(*dsm) * 256); + dsm = nvme_alloc(sizeof(*dsm) * nc); if (!dsm) return -ENOMEM; - nvme_init_dsm(&cmd, cfg.namespace_id, nr, cfg.idr, cfg.idw, cfg.ad, dsm, - sizeof(*dsm) * 256); + nvme_init_dsm_range(dsm, ctx_attrs, nlbs, slbas, nc); + nvme_init_dsm(&cmd, cfg.namespace_id, nc, cfg.idr, cfg.idw, cfg.ad, dsm, + sizeof(*dsm) * nc); err = nvme_submit_io_passthru(hdl, &cmd, NULL); if (err < 0) nvme_show_error("data-set management: %s", nvme_strerror(err));