Commit 6bcd3588 authored by Benjamin Saunders's avatar Benjamin Saunders Committed by Jim Harris
Browse files

nvme: add support for write uncorrectable command



Change-Id: I9fb7a998f7c13ce53cba630a895e8e11cf5f4a1c
Signed-off-by: default avatarBenjamin Saunders <bsaunders@google.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/467559


Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 6956b0ec
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ can support weighted round robin arbitration feature with submission queue.
Added `arbitration_burst` option for arbitration feature, and added three
`low/medium/high_priority_weight` options for weighted round robin arbitration.

Added `spdk_nvme_ns_cmd_write_uncorrectable`.

### iSCSI

Portals may no longer be associated with a cpumask. The scheduling of
+22 −0
Original line number Diff line number Diff line
@@ -1814,6 +1814,7 @@ enum spdk_nvme_ns_flags {
	SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED	= 0x20, /**< The extended lba format is supported,
							      metadata is transferred as a contiguous
							      part of the logical block that it is associated with */
	SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED	= 0x40, /**< The write uncorrectable command is supported */
};

/**
@@ -1987,6 +1988,27 @@ int spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpai
				  spdk_nvme_cmd_cb cb_fn, void *cb_arg,
				  uint32_t io_flags);

/**
 * Submit a write uncorrectable I/O to the specified NVMe namespace.
 *
 * The command is submitted to a qpair allocated by spdk_nvme_ctrlr_alloc_io_qpair().
 * The user must ensure that only one thread submits I/O on a given qpair at any
 * given time.
 *
 * \param ns NVMe namespace to submit the write uncorrectable I/O.
 * \param qpair I/O queue pair to submit the request.
 * \param lba Starting LBA for this command.
 * \param lba_count Length (in sectors) for the write uncorrectable operation.
 * \param cb_fn Callback function to invoke when the I/O is completed.
 * \param cb_arg Argument to pass to the callback function.
 *
 * \return 0 if successfully submitted, negated errno if an nvme_request structure
 * cannot be allocated for the I/O request.
 */
int spdk_nvme_ns_cmd_write_uncorrectable(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
		uint64_t lba, uint32_t lba_count,
		spdk_nvme_cmd_cb cb_fn, void *cb_arg);

/**
 * \brief Submits a read I/O to the specified NVMe namespace.
 *
+4 −0
Original line number Diff line number Diff line
@@ -91,6 +91,10 @@ nvme_ns_set_identify_data(struct spdk_nvme_ns *ns)
		ns->flags |= SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED;
	}

	if (ns->ctrlr->cdata.oncs.write_unc) {
		ns->flags |= SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED;
	}

	if (nsdata->nsrescap.raw) {
		ns->flags |= SPDK_NVME_NS_RESERVATION_SUPPORTED;
	}
+29 −0
Original line number Diff line number Diff line
@@ -778,6 +778,35 @@ spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q
	return nvme_qpair_submit_request(qpair, req);
}

int
spdk_nvme_ns_cmd_write_uncorrectable(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
				     uint64_t lba, uint32_t lba_count,
				     spdk_nvme_cmd_cb cb_fn, void *cb_arg)
{
	struct nvme_request	*req;
	struct spdk_nvme_cmd	*cmd;
	uint64_t		*tmp_lba;

	if (lba_count == 0 || lba_count > UINT16_MAX + 1) {
		return -EINVAL;
	}

	req = nvme_allocate_request_null(qpair, cb_fn, cb_arg);
	if (req == NULL) {
		return -ENOMEM;
	}

	cmd = &req->cmd;
	cmd->opc = SPDK_NVME_OPC_WRITE_UNCORRECTABLE;
	cmd->nsid = ns->id;

	tmp_lba = (uint64_t *)&cmd->cdw10;
	*tmp_lba = lba;
	cmd->cdw12 = lba_count - 1;

	return nvme_qpair_submit_request(qpair, req);
}

int
spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair,
				    uint32_t type,
+29 −0
Original line number Diff line number Diff line
@@ -564,6 +564,33 @@ test_nvme_ns_cmd_write_zeroes(void)
	cleanup_after_test(&qpair);
}

static void
test_nvme_ns_cmd_write_uncorrectable(void)
{
	struct spdk_nvme_ns	ns = { 0 };
	struct spdk_nvme_ctrlr	ctrlr = { 0 };
	struct spdk_nvme_qpair	qpair;
	spdk_nvme_cmd_cb	cb_fn = NULL;
	void			*cb_arg = NULL;
	uint64_t		cmd_lba;
	uint32_t		cmd_lba_count;
	int			rc;

	prepare_for_test(&ns, &ctrlr, &qpair, 512, 0, 128 * 1024, 0, false);

	rc = spdk_nvme_ns_cmd_write_uncorrectable(&ns, &qpair, 0, 2, cb_fn, cb_arg);
	SPDK_CU_ASSERT_FATAL(rc == 0);
	SPDK_CU_ASSERT_FATAL(g_request != NULL);
	CU_ASSERT(g_request->cmd.opc == SPDK_NVME_OPC_WRITE_UNCORRECTABLE);
	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);
	cleanup_after_test(&qpair);
}

static void
test_nvme_ns_cmd_dataset_management(void)
{
@@ -1405,6 +1432,8 @@ int main(int argc, char **argv)
			       test_nvme_ns_cmd_dataset_management) == NULL
		|| CU_add_test(suite, "io_flags", test_io_flags) == NULL
		|| CU_add_test(suite, "nvme_ns_cmd_write_zeroes", test_nvme_ns_cmd_write_zeroes) == NULL
		|| CU_add_test(suite, "nvme_ns_cmd_write_uncorrectable",
			       test_nvme_ns_cmd_write_uncorrectable) == NULL
		|| CU_add_test(suite, "nvme_ns_cmd_reservation_register",
			       test_nvme_ns_cmd_reservation_register) == NULL
		|| CU_add_test(suite, "nvme_ns_cmd_reservation_release",