Loading include/spdk/nvme.h +22 −0 Original line number Diff line number Diff line Loading @@ -365,6 +365,7 @@ enum nvme_namespace_flags { NVME_NS_DEALLOCATE_SUPPORTED = 0x1, /**< The deallocate 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_WRITE_ZEROES_SUPPORTED = 0x8, /**< The write zeroes command is supported */ }; /** Loading Loading @@ -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_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. * Loading lib/nvme/nvme_ns.c +4 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,10 @@ nvme_ns_construct(struct nvme_namespace *ns, uint16_t id, ns->flags |= NVME_NS_FLUSH_SUPPORTED; } if (ctrlr->cdata.oncs.write_zeroes) { ns->flags |= NVME_NS_WRITE_ZEROES_SUPPORTED; } if (nsdata->nsrescap.raw) { ns->flags |= NVME_NS_RESERVATION_SUPPORTED; } Loading lib/nvme/nvme_ns_cmd.c +32 −0 Original line number Diff line number Diff line Loading @@ -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 nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, uint16_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg) Loading test/lib/nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c +23 −0 Original line number Diff line number Diff line Loading @@ -331,6 +331,28 @@ test_nvme_ns_cmd_flush(void) 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 test_nvme_ns_cmd_deallocate(void) { Loading Loading @@ -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_deallocate testing", test_nvme_ns_cmd_deallocate) == 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(); return CU_get_error(); Loading Loading
include/spdk/nvme.h +22 −0 Original line number Diff line number Diff line Loading @@ -365,6 +365,7 @@ enum nvme_namespace_flags { NVME_NS_DEALLOCATE_SUPPORTED = 0x1, /**< The deallocate 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_WRITE_ZEROES_SUPPORTED = 0x8, /**< The write zeroes command is supported */ }; /** Loading Loading @@ -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_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. * Loading
lib/nvme/nvme_ns.c +4 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,10 @@ nvme_ns_construct(struct nvme_namespace *ns, uint16_t id, ns->flags |= NVME_NS_FLUSH_SUPPORTED; } if (ctrlr->cdata.oncs.write_zeroes) { ns->flags |= NVME_NS_WRITE_ZEROES_SUPPORTED; } if (nsdata->nsrescap.raw) { ns->flags |= NVME_NS_RESERVATION_SUPPORTED; } Loading
lib/nvme/nvme_ns_cmd.c +32 −0 Original line number Diff line number Diff line Loading @@ -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 nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, uint16_t num_ranges, nvme_cb_fn_t cb_fn, void *cb_arg) Loading
test/lib/nvme/unit/nvme_ns_cmd_c/nvme_ns_cmd_ut.c +23 −0 Original line number Diff line number Diff line Loading @@ -331,6 +331,28 @@ test_nvme_ns_cmd_flush(void) 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 test_nvme_ns_cmd_deallocate(void) { Loading Loading @@ -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_deallocate testing", test_nvme_ns_cmd_deallocate) == 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(); return CU_get_error(); Loading