Commit 20c767e7 authored by Haomai Wang's avatar Haomai Wang Committed by Ben Walker
Browse files

nvme: add support for write zeroes command



Change-Id: I07ae5805c434d3c06ac24c1a8e09c761b5506ff4
Signed-off-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 5578f74d
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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 */
};

/**
@@ -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.
 *
+4 −0
Original line number Diff line number Diff line
@@ -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;
	}
+32 −0
Original line number Diff line number Diff line
@@ -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)
+23 −0
Original line number Diff line number Diff line
@@ -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)
{
@@ -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();