diff --git a/src/nvme/api-types.h b/src/nvme/api-types.h index 149ba22c7..08c584a2f 100644 --- a/src/nvme/api-types.h +++ b/src/nvme/api-types.h @@ -74,6 +74,7 @@ struct nvme_identify_args { * @ot: Offset Type; if set @lpo specifies the index into the list * of data structures, otherwise @lpo specifies the byte offset * into the log page. + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_get_log_args { __u64 lpo; @@ -91,6 +92,7 @@ struct nvme_get_log_args { __u8 uuidx; bool rae; bool ot; + bool ish; }; /** @@ -171,6 +173,7 @@ struct nvme_get_features_args { * @lbaf: Logical block address format least significant 4 bits * @rsvd1: Reserved * @lbafu: Logical block address format most significant 2 bits + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_format_nvm_args { __u32 *result; @@ -185,6 +188,7 @@ struct nvme_format_nvm_args { __u8 lbaf; __u8 rsvd1[7]; __u8 lbafu; + bool ish; }; /** @@ -200,6 +204,7 @@ struct nvme_format_nvm_args { * @rsvd1: Reserved * @rsvd2: Reserved * @data: Host Software Specified Fields + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_ns_mgmt_args { __u32 *result; @@ -213,6 +218,7 @@ struct nvme_ns_mgmt_args { __u8 rsvd1[3]; void *rsvd2; struct nvme_ns_mgmt_host_sw_specified *data; + bool ish; }; /** @@ -224,6 +230,7 @@ struct nvme_ns_mgmt_args { * @timeout: Timeout in ms * @nsid: Namespace ID to execute attach selection * @sel: Attachment selection, see &enum nvme_ns_attach_sel + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_ns_attach_args { __u32 *result; @@ -233,6 +240,7 @@ struct nvme_ns_attach_args { __u32 timeout; __u32 nsid; enum nvme_ns_attach_sel sel; + bool ish; }; /** @@ -244,6 +252,7 @@ struct nvme_ns_attach_args { * @offset: Offset in the firmware data * @data: Userspace address of the firmware data * @data_len: Length of data in this command in bytes + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_fw_download_args { __u32 *result; @@ -253,6 +262,7 @@ struct nvme_fw_download_args { __u32 timeout; __u32 offset; __u32 data_len; + bool ish; }; /** @@ -264,6 +274,7 @@ struct nvme_fw_download_args { * @result: The command completion result from CQE dword0 * @slot: Firmware slot to commit the downloaded image * @bpid: Set to true to select the boot partition id + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_fw_commit_args { __u32 *result; @@ -273,6 +284,7 @@ struct nvme_fw_commit_args { enum nvme_fw_commit_ca action; __u8 slot; bool bpid; + bool ish; }; /** @@ -289,6 +301,7 @@ struct nvme_fw_commit_args { * @spsp0: Security Protocol Specific field * @spsp1: Security Protocol Specific field * @secp: Security Protocol + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_security_send_args { __u32 *result; @@ -303,6 +316,7 @@ struct nvme_security_send_args { __u8 spsp0; __u8 spsp1; __u8 secp; + bool ish; }; /** @@ -319,6 +333,7 @@ struct nvme_security_send_args { * @spsp0: Security Protocol Specific field * @spsp1: Security Protocol Specific field * @secp: Security Protocol + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_security_receive_args { __u32 *result; @@ -333,6 +348,7 @@ struct nvme_security_receive_args { __u8 spsp0; __u8 spsp1; __u8 secp; + bool ish; }; /** @@ -513,6 +529,7 @@ struct nvme_get_property_args { * @oipbp: Set to overwrite invert pattern between passes * @nodas: Set to not deallocate blocks after sanitizing * @emvs: Set to enter media verification state + * @ish: Ignore Shutdown (for NVMe-MI command) */ struct nvme_sanitize_nvm_args { __u32 *result; @@ -526,6 +543,7 @@ struct nvme_sanitize_nvm_args { bool oipbp; bool nodas; bool emvs; + bool ish; }; /** diff --git a/src/nvme/ioctl.c b/src/nvme/ioctl.c index a887ae483..7fc14bd9c 100644 --- a/src/nvme/ioctl.c +++ b/src/nvme/ioctl.c @@ -285,6 +285,8 @@ int nvme_identify(struct nvme_identify_args *args) int nvme_get_log(struct nvme_get_log_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_get_log_args, ot, __u64); + const size_t size_v2 = sizeof_args(struct nvme_get_log_args, ish, __u64); __u32 numd = (args->len >> 2) - 1; __u16 numdu = numd >> 16, numdl = numd & 0xffff; @@ -313,7 +315,7 @@ int nvme_get_log(struct nvme_get_log_args *args) .timeout_ms = args->timeout, }; - if (args->args_size < sizeof(struct nvme_get_log_args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -373,6 +375,8 @@ static void nvme_uring_cmd_exit(struct io_uring *ring) static int nvme_uring_cmd_admin_passthru_async(struct io_uring *ring, struct nvme_get_log_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_get_log_args, ot, __u64); + const size_t size_v2 = sizeof_args(struct nvme_get_log_args, ish, __u64); struct io_uring_sqe *sqe; struct nvme_uring_cmd *cmd; int ret; @@ -392,7 +396,7 @@ static int nvme_uring_cmd_admin_passthru_async(struct io_uring *ring, struct nvm NVME_SET(!!args->ot, LOG_CDW14_OT) | NVME_SET(args->csi, LOG_CDW14_CSI); - if (args->args_size < sizeof(struct nvme_get_log_args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1501,9 +1505,10 @@ int nvme_format_nvm(struct nvme_format_nvm_args *args) { const size_t size_v1 = sizeof_args(struct nvme_format_nvm_args, lbaf, __u64); const size_t size_v2 = sizeof_args(struct nvme_format_nvm_args, lbafu, __u64); + const size_t size_v3 = sizeof_args(struct nvme_format_nvm_args, ish, __u64); __u32 cdw10; - if (args->args_size < size_v1 || args->args_size > size_v2) { + if (args->args_size < size_v1 || args->args_size > size_v3) { errno = EINVAL; return -1; } @@ -1533,10 +1538,11 @@ int nvme_ns_mgmt(struct nvme_ns_mgmt_args *args) { const size_t size_v1 = sizeof_args(struct nvme_ns_mgmt_args, csi, __u64); const size_t size_v2 = sizeof_args(struct nvme_ns_mgmt_args, data, __u64); + const size_t size_v3 = sizeof_args(struct nvme_ns_mgmt_args, ish, __u64); __u32 cdw10 = NVME_SET(args->sel, NAMESPACE_MGMT_CDW10_SEL); __u32 cdw11 = NVME_SET(args->csi, NAMESPACE_MGMT_CDW11_CSI); - if (args->args_size < size_v1 || args->args_size > size_v2) { + if (args->args_size < size_v1 || args->args_size > size_v3) { errno = EINVAL; return -1; } @@ -1566,6 +1572,8 @@ int nvme_ns_mgmt(struct nvme_ns_mgmt_args *args) int nvme_ns_attach(struct nvme_ns_attach_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_ns_attach_args, sel, __u64); + const size_t size_v2 = sizeof_args(struct nvme_ns_attach_args, ish, __u64); __u32 cdw10 = NVME_SET(args->sel, NAMESPACE_ATTACH_CDW10_SEL); struct nvme_passthru_cmd cmd = { @@ -1577,7 +1585,7 @@ int nvme_ns_attach(struct nvme_ns_attach_args *args) .timeout_ms = args->timeout, }; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1586,6 +1594,8 @@ int nvme_ns_attach(struct nvme_ns_attach_args *args) int nvme_fw_download(struct nvme_fw_download_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_fw_download_args, data_len, __u64); + const size_t size_v2 = sizeof_args(struct nvme_fw_download_args, ish, __u64); __u32 cdw10 = (args->data_len >> 2) - 1; __u32 cdw11 = args->offset >> 2; @@ -1598,7 +1608,7 @@ int nvme_fw_download(struct nvme_fw_download_args *args) .timeout_ms = args->timeout, }; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1607,6 +1617,8 @@ int nvme_fw_download(struct nvme_fw_download_args *args) int nvme_fw_commit(struct nvme_fw_commit_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_fw_commit_args, bpid, __u64); + const size_t size_v2 = sizeof_args(struct nvme_fw_commit_args, ish, __u64); __u32 cdw10 = NVME_SET(args->slot, FW_COMMIT_CDW10_FS) | NVME_SET(args->action, FW_COMMIT_CDW10_CA) | NVME_SET(args->bpid, FW_COMMIT_CDW10_BPID); @@ -1617,7 +1629,7 @@ int nvme_fw_commit(struct nvme_fw_commit_args *args) .timeout_ms = args->timeout, }; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1626,6 +1638,8 @@ int nvme_fw_commit(struct nvme_fw_commit_args *args) int nvme_security_send(struct nvme_security_send_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_security_send_args, secp, __u64); + const size_t size_v2 = sizeof_args(struct nvme_security_send_args, ish, __u64); __u32 cdw10 = NVME_SET(args->secp, SECURITY_SECP) | NVME_SET(args->spsp0, SECURITY_SPSP0) | NVME_SET(args->spsp1, SECURITY_SPSP1) | @@ -1642,7 +1656,7 @@ int nvme_security_send(struct nvme_security_send_args *args) .timeout_ms = args->timeout, }; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1651,6 +1665,8 @@ int nvme_security_send(struct nvme_security_send_args *args) int nvme_security_receive(struct nvme_security_receive_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_security_receive_args, secp, __u64); + const size_t size_v2 = sizeof_args(struct nvme_security_receive_args, ish, __u64); __u32 cdw10 = NVME_SET(args->secp, SECURITY_SECP) | NVME_SET(args->spsp0, SECURITY_SPSP0) | NVME_SET(args->spsp1, SECURITY_SPSP1) | @@ -1667,7 +1683,7 @@ int nvme_security_receive(struct nvme_security_receive_args *args) .timeout_ms = args->timeout, }; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1858,9 +1874,10 @@ int nvme_sanitize_nvm(struct nvme_sanitize_nvm_args *args) { const size_t size_v1 = sizeof_args(struct nvme_sanitize_nvm_args, nodas, __u64); const size_t size_v2 = sizeof_args(struct nvme_sanitize_nvm_args, emvs, __u64); + const size_t size_v3 = sizeof_args(struct nvme_sanitize_nvm_args, ish, __u64); __u32 cdw10, cdw11; - if (args->args_size < size_v1 || args->args_size > size_v2) { + if (args->args_size < size_v1 || args->args_size > size_v3) { errno = EINVAL; return -1; } diff --git a/src/nvme/mi.c b/src/nvme/mi.c index 14c71d75e..8ce839515 100644 --- a/src/nvme/mi.c +++ b/src/nvme/mi.c @@ -852,7 +852,7 @@ int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, __u32 data_len, void *data, __u32 metadata_len, void *metadata, __u32 timeout_ms, __u32 *result) { - /* Input parameters flags, rsvd, metadata, metadata_len are not used */ + /* Input parameters rsvd, metadata, metadata_len are not used */ struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; @@ -895,10 +895,11 @@ int nvme_mi_admin_admin_passthru(nvme_mi_ctrl_t ctrl, __u8 opcode, __u8 flags, req_hdr.cdw14 = cpu_to_le32(cdw14); req_hdr.cdw15 = cpu_to_le32(cdw15); req_hdr.doff = 0; + req_hdr.flags = flags; if (data_len != 0) { req_hdr.dlen = cpu_to_le32(data_len); /* Bit 0 set to 1 means DLEN contains a value */ - req_hdr.flags = 0x1; + req_hdr.flags |= 0x1; } if (has_write_data) { @@ -1030,6 +1031,8 @@ static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, const struct nvme_get_log_args *args, off_t offset, size_t *lenp, bool final) { + const size_t size_v1 = sizeof_args(struct nvme_get_log_args, ot, __u64); + const size_t size_v2 = sizeof_args(struct nvme_get_log_args, ish, __u64); __u64 log_page_offset = args->lpo + offset; struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; @@ -1039,6 +1042,11 @@ static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, __u32 ndw; int rc; + if (args->args_size < size_v1 || args->args_size > size_v2) { + errno = EINVAL; + return -1; + } + /* MI spec requires that the data length field is less than or equal * to 4096 */ len = *lenp; @@ -1069,8 +1077,10 @@ static int __nvme_mi_admin_get_log(nvme_mi_ctrl_t ctrl, (args->ot ? 1 : 0) << 23 | args->uuidx); req_hdr.flags = 0x1; - req_hdr.dlen = cpu_to_le32(len & 0xffffffff); + if (args->args_size == size_v2) + req_hdr.flags |= (((args->ish) ? 1 : 0) << 0x2); + req_hdr.dlen = cpu_to_le32(len & 0xffffffff); nvme_mi_admin_init_resp(&resp, &resp_hdr); resp.data = args->log + offset; resp.data_len = len; @@ -1268,14 +1278,15 @@ int nvme_mi_admin_get_ana_log_atomic(nvme_mi_ctrl_t ctrl, bool rgo, bool rae, int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl, struct nvme_security_send_args *args) { - + const size_t size_v1 = sizeof_args(struct nvme_security_send_args, secp, __u64); + const size_t size_v2 = sizeof_args(struct nvme_security_send_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1296,6 +1307,8 @@ int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl, req_hdr.cdw11 = cpu_to_le32(args->data_len & 0xffffffff); req_hdr.flags = 0x1; + if (args->args_size == size_v2) + req_hdr.flags |= (((args->ish) ? 1 : 0) << 0x2); req_hdr.dlen = cpu_to_le32(args->data_len & 0xffffffff); req.data = args->data; req.data_len = args->data_len; @@ -1312,14 +1325,15 @@ int nvme_mi_admin_security_send(nvme_mi_ctrl_t ctrl, int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl, struct nvme_security_receive_args *args) { - + const size_t size_v1 = sizeof_args(struct nvme_security_receive_args, secp, __u64); + const size_t size_v2 = sizeof_args(struct nvme_security_receive_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1340,6 +1354,8 @@ int nvme_mi_admin_security_recv(nvme_mi_ctrl_t ctrl, req_hdr.cdw11 = cpu_to_le32(args->data_len & 0xffffffff); req_hdr.flags = 0x1; + if (args->args_size == size_v2) + req_hdr.flags |= (((args->ish) ? 1 : 0) << 0x2); req_hdr.dlen = cpu_to_le32(args->data_len & 0xffffffff); nvme_mi_admin_init_resp(&resp, &resp_hdr); @@ -1505,6 +1521,7 @@ int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl, { const size_t size_v1 = sizeof_args(struct nvme_ns_mgmt_args, csi, __u64); const size_t size_v2 = sizeof_args(struct nvme_ns_mgmt_args, data, __u64); + const size_t size_v3 = sizeof_args(struct nvme_ns_mgmt_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; @@ -1512,7 +1529,7 @@ int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl, int rc; size_t data_len; - if (args->args_size < size_v1 || args->args_size > size_v2) { + if (args->args_size < size_v1 || args->args_size > size_v3) { errno = EINVAL; return -1; } @@ -1543,6 +1560,9 @@ int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl, req_hdr.flags = 0x1; } + if (args->args_size == size_v3) + req_hdr.flags |= (((args->ish) ? 1 : 0) << 0x2); + nvme_mi_admin_init_resp(&resp, &resp_hdr); rc = nvme_mi_submit(ctrl->ep, &req, &resp); @@ -1555,13 +1575,15 @@ int nvme_mi_admin_ns_mgmt(nvme_mi_ctrl_t ctrl, int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl, struct nvme_ns_attach_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_ns_attach_args, sel, __u64); + const size_t size_v2 = sizeof_args(struct nvme_ns_attach_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1575,6 +1597,8 @@ int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl, req.data_len = sizeof(*args->ctrlist); req_hdr.dlen = cpu_to_le32(sizeof(*args->ctrlist)); req_hdr.flags = 0x1; + if (args->args_size == size_v2) + req_hdr.flags |= (((args->ish) ? 1 : 0) << 0x2); nvme_mi_admin_init_resp(&resp, &resp_hdr); @@ -1588,13 +1612,15 @@ int nvme_mi_admin_ns_attach(nvme_mi_ctrl_t ctrl, int nvme_mi_admin_fw_download(nvme_mi_ctrl_t ctrl, struct nvme_fw_download_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_fw_download_args, data_len, __u64); + const size_t size_v2 = sizeof_args(struct nvme_fw_download_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1618,6 +1644,8 @@ int nvme_mi_admin_fw_download(nvme_mi_ctrl_t ctrl, req.data_len = args->data_len; req_hdr.dlen = cpu_to_le32(args->data_len); req_hdr.flags = 0x1; + if (args->args_size == size_v2) + req_hdr.flags |= (((args->ish) ? 1 : 0) << 0x2); nvme_mi_admin_init_resp(&resp, &resp_hdr); @@ -1631,13 +1659,15 @@ int nvme_mi_admin_fw_download(nvme_mi_ctrl_t ctrl, int nvme_mi_admin_fw_commit(nvme_mi_ctrl_t ctrl, struct nvme_fw_commit_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_fw_commit_args, bpid, __u64); + const size_t size_v2 = sizeof_args(struct nvme_fw_commit_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1648,6 +1678,8 @@ int nvme_mi_admin_fw_commit(nvme_mi_ctrl_t ctrl, req_hdr.cdw10 = cpu_to_le32(((__u32)(args->bpid & 0x1) << 31) | ((args->action & 0x7) << 3) | ((args->slot & 0x7) << 0)); + if (args->args_size == size_v2) + req_hdr.flags = (((args->ish) ? 1 : 0) << 0x2); nvme_mi_admin_init_resp(&resp, &resp_hdr); @@ -1661,13 +1693,15 @@ int nvme_mi_admin_fw_commit(nvme_mi_ctrl_t ctrl, int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl, struct nvme_format_nvm_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_format_nvm_args, lbafu, __u64); + const size_t size_v2 = sizeof_args(struct nvme_format_nvm_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1682,6 +1716,8 @@ int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl, | ((args->pi & 0x7) << 5) | ((args->mset & 0x1) << 4) | ((args->lbaf & 0xf) << 0)); + if (args->args_size == size_v2) + req_hdr.flags = (((args->ish) ? 1 : 0) << 0x2); nvme_mi_admin_init_resp(&resp, &resp_hdr); @@ -1695,13 +1731,15 @@ int nvme_mi_admin_format_nvm(nvme_mi_ctrl_t ctrl, int nvme_mi_admin_sanitize_nvm(nvme_mi_ctrl_t ctrl, struct nvme_sanitize_nvm_args *args) { + const size_t size_v1 = sizeof_args(struct nvme_sanitize_nvm_args, emvs, __u64); + const size_t size_v2 = sizeof_args(struct nvme_sanitize_nvm_args, ish, __u64); struct nvme_mi_admin_resp_hdr resp_hdr; struct nvme_mi_admin_req_hdr req_hdr; struct nvme_mi_resp resp; struct nvme_mi_req req; int rc; - if (args->args_size < sizeof(*args)) { + if (args->args_size < size_v1 || args->args_size > size_v2) { errno = EINVAL; return -1; } @@ -1715,6 +1753,8 @@ int nvme_mi_admin_sanitize_nvm(nvme_mi_ctrl_t ctrl, | ((args->ause ? 1 : 0) << 3) | ((args->sanact & 0x7) << 0)); req_hdr.cdw11 = cpu_to_le32(args->ovrpat); + if (args->args_size == size_v2) + req_hdr.flags = (((args->ish) ? 1 : 0) << 0x2); nvme_mi_admin_init_resp(&resp, &resp_hdr);