Commit 5e4d957e authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Konrad Sztyber
Browse files

nvmf: Identify command supports IOCS NVM NS data structure



Add minimum change to support and verify it by writing unit tests.
We will revisit this feature when we find any OS uses Storage Tag.

Signed-off-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Change-Id: I0a9456d099f8fcf735ed773bec18e82dfbe1112e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/24112


Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
parent 481e17c3
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -2981,6 +2981,18 @@ nvmf_ns_identify_iocs_zns(struct spdk_nvmf_ns *ns,
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static int
nvmf_ns_identify_iocs_nvm(struct spdk_nvmf_ns *ns,
			  struct spdk_nvme_cpl *rsp,
			  struct spdk_nvme_nvm_ns_data *nsdata_nvm)
{
	nvmf_bdev_ctrlr_identify_iocs_nvm(ns, nsdata_nvm);

	rsp->status.sct = SPDK_NVME_SCT_GENERIC;
	rsp->status.sc = SPDK_NVME_SC_SUCCESS;
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

int
spdk_nvmf_ns_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
				    struct spdk_nvme_cmd *cmd,
@@ -3002,6 +3014,11 @@ spdk_nvmf_ns_identify_iocs_specific(struct spdk_nvmf_ctrlr *ctrlr,
	switch (csi) {
	case SPDK_NVME_CSI_ZNS:
		return nvmf_ns_identify_iocs_zns(ns, cmd, rsp, nsdata);
	case SPDK_NVME_CSI_NVM:
		if (!ctrlr->dif_insert_or_strip) {
			return nvmf_ns_identify_iocs_nvm(ns, rsp, nsdata);
		}
		break;
	default:
		break;
	}
+52 −0
Original line number Diff line number Diff line
@@ -197,6 +197,58 @@ nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *n
	}
}

void
nvmf_bdev_ctrlr_identify_iocs_nvm(struct spdk_nvmf_ns *ns,
				  struct spdk_nvme_nvm_ns_data *nsdata_nvm)
{
	struct spdk_bdev *bdev = ns->bdev;
	uint8_t _16bpists;
	uint32_t sts, pif;

	if (spdk_bdev_get_dif_type(bdev) == SPDK_DIF_DISABLE) {
		return;
	}

	pif = spdk_bdev_get_dif_pi_format(bdev);

	/*
	 * 16BPISTS shall be 1 for 32/64b Guard PI.
	 * STCRS shall be 1 if 16BPISTS is 1.
	 * 16 is the minimum value of STS for 32b Guard PI.
	 */
	switch (pif) {
	case SPDK_DIF_PI_FORMAT_16:
		_16bpists = 0;
		sts = 0;
		break;
	case SPDK_DIF_PI_FORMAT_32:
		_16bpists = 1;
		sts = 16;
		break;
	case SPDK_DIF_PI_FORMAT_64:
		_16bpists = 1;
		sts = 0;
		break;
	default:
		SPDK_WARNLOG("PI format %u is not supported\n", pif);
		return;
	}

	/* For 16b Guard PI, Storage Tag is not available because we set STS to 0.
	 * In this case, we do not have to set 16BPISTM to 1. For simplicity,
	 * set 16BPISTM to 0 and set LBSTM to all zeroes.
	 *
	 * We will revisit here when we find any OS uses Storage Tag.
	 */
	nsdata_nvm->lbstm = 0;
	nsdata_nvm->pic._16bpistm = 0;

	nsdata_nvm->pic._16bpists = _16bpists;
	nsdata_nvm->pic.stcrs = 0;
	nsdata_nvm->elbaf[0].sts = sts;
	nsdata_nvm->elbaf[0].pif = pif;
}

static void
nvmf_bdev_ctrlr_get_rw_params(const struct spdk_nvme_cmd *cmd, uint64_t *start_lba,
			      uint64_t *num_blocks)
+2 −0
Original line number Diff line number Diff line
@@ -391,6 +391,8 @@ bool nvmf_ctrlr_use_zcopy(struct spdk_nvmf_request *req);

void nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata,
				 bool dif_insert_or_strip);
void nvmf_bdev_ctrlr_identify_iocs_nvm(struct spdk_nvmf_ns *ns,
				       struct spdk_nvme_nvm_ns_data *nsdata_nvm);
int nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
			     struct spdk_io_channel *ch, struct spdk_nvmf_request *req);
int nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
+50 −22
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ struct spdk_bdev {
	uint32_t zone_size;
	uint32_t max_open_zones;
	uint32_t max_active_zones;
	enum spdk_dif_type dif_type;
};

#define MAX_OPEN_ZONES 12
@@ -253,6 +254,22 @@ nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *n
	nsdata->lbaf[0].lbads = spdk_u32log2(512);
}

void
nvmf_bdev_ctrlr_identify_iocs_nvm(struct spdk_nvmf_ns *ns,
				  struct spdk_nvme_nvm_ns_data *nsdata_nvm)
{
	if (ns->bdev->dif_type == SPDK_DIF_DISABLE) {
		return;
	}

	nsdata_nvm->lbstm = 0;
	nsdata_nvm->pic._16bpists = 0;
	nsdata_nvm->pic._16bpistm = 1;
	nsdata_nvm->pic.stcrs = 0;
	nsdata_nvm->elbaf[0].sts = 16;
	nsdata_nvm->elbaf[0].pif = SPDK_DIF_PI_FORMAT_32;
}

struct spdk_nvmf_ns *
spdk_nvmf_subsystem_get_first_ns(struct spdk_nvmf_subsystem *subsystem)
{
@@ -1182,7 +1199,8 @@ test_identify_ns_iocs_specific(void)
	struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair };
	struct spdk_nvme_cmd cmd = {};
	struct spdk_nvme_cpl rsp = {};
	struct spdk_nvme_zns_ns_data nsdata = {};
	struct spdk_nvme_zns_ns_data nsdata_zns = {};
	struct spdk_nvme_nvm_ns_data nsdata_nvm = {};
	struct spdk_bdev bdev[2] = {{.blockcnt = 1234, .zoned = true, .zone_size = ZONE_SIZE, .max_open_zones = MAX_OPEN_ZONES, .max_active_zones = MAX_ACTIVE_ZONES}, {.blockcnt = 5678}};
	struct spdk_nvmf_ns ns[2] = {{.bdev = &bdev[0]}, {.bdev = &bdev[1]}};
	struct spdk_nvmf_ns *ns_arr[2] = {&ns[0], &ns[1]};
@@ -1198,53 +1216,63 @@ test_identify_ns_iocs_specific(void)

	/* Invalid ZNS NSID 0 */
	cmd.nsid = 0;
	memset(&nsdata, 0xFF, sizeof(nsdata));
	memset(&nsdata_zns, 0xFF, sizeof(nsdata_zns));
	memset(&rsp, 0, sizeof(rsp));
	CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
			&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
			&nsdata_zns, sizeof(nsdata_zns)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
	CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
	CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
	CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
	CU_ASSERT(spdk_mem_all_zero(&nsdata_zns, sizeof(nsdata_zns)));

	/* Valid ZNS NSID 1 */
	cmd.nsid = 1;
	memset(&nsdata, 0xFF, sizeof(nsdata));
	memset(&nsdata_zns, 0xFF, sizeof(nsdata_zns));
	memset(&rsp, 0, sizeof(rsp));
	CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
			&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
			&nsdata_zns, sizeof(nsdata_zns)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
	CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
	CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
	CU_ASSERT(nsdata.ozcs.read_across_zone_boundaries == 1);
	CU_ASSERT(nsdata.mar == MAX_ACTIVE_ZONES - 1);
	CU_ASSERT(nsdata.mor == MAX_OPEN_ZONES - 1);
	CU_ASSERT(nsdata.lbafe[0].zsze == ZONE_SIZE);
	nsdata.ozcs.read_across_zone_boundaries = 0;
	nsdata.mar = 0;
	nsdata.mor = 0;
	nsdata.lbafe[0].zsze = 0;
	CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
	CU_ASSERT(nsdata_zns.ozcs.read_across_zone_boundaries == 1);
	CU_ASSERT(nsdata_zns.mar == MAX_ACTIVE_ZONES - 1);
	CU_ASSERT(nsdata_zns.mor == MAX_OPEN_ZONES - 1);
	CU_ASSERT(nsdata_zns.lbafe[0].zsze == ZONE_SIZE);
	nsdata_zns.ozcs.read_across_zone_boundaries = 0;
	nsdata_zns.mar = 0;
	nsdata_zns.mor = 0;
	nsdata_zns.lbafe[0].zsze = 0;
	CU_ASSERT(spdk_mem_all_zero(&nsdata_zns, sizeof(nsdata_zns)));

	cmd.cdw11_bits.identify.csi = SPDK_NVME_CSI_NVM;

	/* Valid NVM NSID 2 */
	/* Valid NVM NSID 2 with DIF type 1 */
	bdev[1].dif_type = SPDK_DIF_TYPE1;
	cmd.nsid = 2;
	memset(&nsdata, 0xFF, sizeof(nsdata));
	memset(&nsdata_nvm, 0xFF, sizeof(nsdata_nvm));
	memset(&rsp, 0, sizeof(rsp));
	CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
			&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
			&nsdata_nvm, sizeof(nsdata_nvm)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
	CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
	CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS);
	CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
	CU_ASSERT(nsdata_nvm.lbstm == 0);
	CU_ASSERT(nsdata_nvm.pic._16bpists == 0);
	CU_ASSERT(nsdata_nvm.pic._16bpistm == 1);
	CU_ASSERT(nsdata_nvm.pic.stcrs == 0);
	CU_ASSERT(nsdata_nvm.elbaf[0].sts == 16);
	CU_ASSERT(nsdata_nvm.elbaf[0].pif == SPDK_DIF_PI_FORMAT_32);
	nsdata_nvm.pic._16bpistm = 0;
	nsdata_nvm.elbaf[0].sts = 0;
	nsdata_nvm.elbaf[0].pif = 0;
	CU_ASSERT(spdk_mem_all_zero(&nsdata_nvm, sizeof(nsdata_nvm)));

	/* Invalid NVM NSID 3 */
	cmd.nsid = 0;
	memset(&nsdata, 0xFF, sizeof(nsdata));
	memset(&nsdata_nvm, 0xFF, sizeof(nsdata_nvm));
	memset(&rsp, 0, sizeof(rsp));
	CU_ASSERT(spdk_nvmf_ns_identify_iocs_specific(&ctrlr, &cmd, &rsp,
			&nsdata, sizeof(nsdata)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
			&nsdata_nvm, sizeof(nsdata_nvm)) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
	CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC);
	CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT);
	CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata)));
	CU_ASSERT(spdk_mem_all_zero(&nsdata_nvm, sizeof(nsdata_nvm)));

	spdk_bit_array_free(&ctrlr.visible_ns);
}
+9 −0
Original line number Diff line number Diff line
@@ -123,6 +123,15 @@ spdk_bdev_get_num_blocks(const struct spdk_bdev *bdev)
	return bdev->blockcnt;
}

/* We have to use the typedef in the function declaration to appease astyle. */
typedef enum spdk_dif_pi_format spdk_dif_pi_format_t;

spdk_dif_pi_format_t
spdk_bdev_get_dif_pi_format(const struct spdk_bdev *bdev)
{
	return bdev->dif_pi_format;
}

DEFINE_STUB(spdk_bdev_comparev_and_writev_blocks, int,
	    (struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
	     struct iovec *compare_iov, int compare_iovcnt,
Loading