nvme: add support for write zeroes command
Change-Id: I07ae5805c434d3c06ac24c1a8e09c761b5506ff4 Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
5578f74dd4
commit
20c767e796
@ -365,6 +365,7 @@ enum nvme_namespace_flags {
|
|||||||
NVME_NS_DEALLOCATE_SUPPORTED = 0x1, /**< The deallocate command is supported */
|
NVME_NS_DEALLOCATE_SUPPORTED = 0x1, /**< The deallocate command is supported */
|
||||||
NVME_NS_FLUSH_SUPPORTED = 0x2, /**< The flush command is supported */
|
NVME_NS_FLUSH_SUPPORTED = 0x2, /**< The flush command is supported */
|
||||||
NVME_NS_RESERVATION_SUPPORTED = 0x4, /**< The reservation command is supported */
|
NVME_NS_RESERVATION_SUPPORTED = 0x4, /**< The reservation command is supported */
|
||||||
|
NVME_NS_WRITE_ZEROES_SUPPORTED = 0x8, /**< The write zeroes command is supported */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -440,6 +441,27 @@ int nvme_ns_cmd_writev(struct nvme_namespace *ns, uint64_t lba, uint32_t lba_cou
|
|||||||
nvme_req_reset_sgl_fn_t reset_sgl_fn,
|
nvme_req_reset_sgl_fn_t reset_sgl_fn,
|
||||||
nvme_req_next_sge_fn_t next_sge_fn);
|
nvme_req_next_sge_fn_t next_sge_fn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Submits a write zeroes I/O to the specified NVMe namespace.
|
||||||
|
*
|
||||||
|
* \param ns NVMe namespace to submit the write zeroes I/O
|
||||||
|
* \param lba starting LBA for this command
|
||||||
|
* \param lba_count length (in sectors) for the write zero operation
|
||||||
|
* \param cb_fn callback function to invoke when the I/O is completed
|
||||||
|
* \param cb_arg argument to pass to the callback function
|
||||||
|
* \param io_flags set flags, defined by the NVME_IO_FLAGS_* entries
|
||||||
|
* in spdk/nvme_spec.h, for this I/O.
|
||||||
|
*
|
||||||
|
* \return 0 if successfully submitted, ENOMEM if an nvme_request
|
||||||
|
* structure cannot be allocated for the I/O request
|
||||||
|
*
|
||||||
|
* This function is thread safe and can be called at any point after
|
||||||
|
* nvme_register_io_thread().
|
||||||
|
*/
|
||||||
|
int nvme_ns_cmd_write_zeroes(struct nvme_namespace *ns, uint64_t lba,
|
||||||
|
uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg,
|
||||||
|
uint32_t io_flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Submits a read I/O to the specified NVMe namespace.
|
* \brief Submits a read I/O to the specified NVMe namespace.
|
||||||
*
|
*
|
||||||
|
@ -126,6 +126,10 @@ nvme_ns_construct(struct nvme_namespace *ns, uint16_t id,
|
|||||||
ns->flags |= NVME_NS_FLUSH_SUPPORTED;
|
ns->flags |= NVME_NS_FLUSH_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctrlr->cdata.oncs.write_zeroes) {
|
||||||
|
ns->flags |= NVME_NS_WRITE_ZEROES_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (nsdata->nsrescap.raw) {
|
if (nsdata->nsrescap.raw) {
|
||||||
ns->flags |= NVME_NS_RESERVATION_SUPPORTED;
|
ns->flags |= NVME_NS_RESERVATION_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -258,6 +258,38 @@ nvme_ns_cmd_writev(struct nvme_namespace *ns, uint64_t lba, uint32_t lba_count,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nvme_ns_cmd_write_zeroes(struct nvme_namespace *ns, uint64_t lba,
|
||||||
|
uint32_t lba_count, nvme_cb_fn_t cb_fn, void *cb_arg,
|
||||||
|
uint32_t io_flags)
|
||||||
|
{
|
||||||
|
struct nvme_request *req;
|
||||||
|
struct nvme_command *cmd;
|
||||||
|
uint64_t *tmp_lba;
|
||||||
|
|
||||||
|
if (lba_count == 0) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
req = nvme_allocate_request_null(cb_fn, cb_arg);
|
||||||
|
if (req == NULL) {
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = &req->cmd;
|
||||||
|
cmd->opc = NVME_OPC_WRITE_ZEROES;
|
||||||
|
cmd->nsid = ns->id;
|
||||||
|
|
||||||
|
tmp_lba = (uint64_t *)&cmd->cdw10;
|
||||||
|
*tmp_lba = lba;
|
||||||
|
cmd->cdw12 = lba_count - 1;
|
||||||
|
cmd->cdw12 |= io_flags;
|
||||||
|
|
||||||
|
nvme_ctrlr_submit_io_request(ns->ctrlr, req);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
|
nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
|
||||||
uint16_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg)
|
uint16_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg)
|
||||||
|
@ -331,6 +331,28 @@ test_nvme_ns_cmd_flush(void)
|
|||||||
nvme_free_request(g_request);
|
nvme_free_request(g_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nvme_ns_cmd_write_zeroes(void)
|
||||||
|
{
|
||||||
|
struct nvme_namespace ns = { 0 };
|
||||||
|
struct nvme_controller ctrlr = { 0 };
|
||||||
|
nvme_cb_fn_t cb_fn = NULL;
|
||||||
|
void *cb_arg = NULL;
|
||||||
|
uint64_t cmd_lba;
|
||||||
|
uint32_t cmd_lba_count;
|
||||||
|
|
||||||
|
prepare_for_test(&ns, &ctrlr, 512, 128 * 1024, 0);
|
||||||
|
|
||||||
|
nvme_ns_cmd_write_zeroes(&ns, 0, 2, cb_fn, cb_arg, 0);
|
||||||
|
CU_ASSERT(g_request->cmd.opc == NVME_OPC_WRITE_ZEROES);
|
||||||
|
CU_ASSERT(g_request->cmd.nsid == ns.id);
|
||||||
|
nvme_cmd_interpret_rw(&g_request->cmd, &cmd_lba, &cmd_lba_count);
|
||||||
|
CU_ASSERT_EQUAL(cmd_lba, 0);
|
||||||
|
CU_ASSERT_EQUAL(cmd_lba_count, 2);
|
||||||
|
|
||||||
|
nvme_free_request(g_request);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_nvme_ns_cmd_deallocate(void)
|
test_nvme_ns_cmd_deallocate(void)
|
||||||
{
|
{
|
||||||
@ -426,6 +448,7 @@ int main(int argc, char **argv)
|
|||||||
|| CU_add_test(suite, "nvme_ns_cmd_flush testing", test_nvme_ns_cmd_flush) == NULL
|
|| CU_add_test(suite, "nvme_ns_cmd_flush testing", test_nvme_ns_cmd_flush) == NULL
|
||||||
|| CU_add_test(suite, "nvme_ns_cmd_deallocate testing", test_nvme_ns_cmd_deallocate) == NULL
|
|| CU_add_test(suite, "nvme_ns_cmd_deallocate testing", test_nvme_ns_cmd_deallocate) == NULL
|
||||||
|| CU_add_test(suite, "io_flags", test_io_flags) == NULL
|
|| CU_add_test(suite, "io_flags", test_io_flags) == NULL
|
||||||
|
|| CU_add_test(suite, "nvme_ns_cmd_write_zeroes testing", test_nvme_ns_cmd_write_zeroes) == NULL
|
||||||
) {
|
) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
Loading…
Reference in New Issue
Block a user