Commit 7bbeb80a authored by Ankit Kumar's avatar Ankit Kumar Committed by Tomasz Zawadzki
Browse files

nvme: support 64 LBA formats for NVM and ZNS command set



Format LBA size (FLBAS) is updated to have:
Bit 3:0 as least significant 4 bits for format index
Bit 6:5 as most significant 2 bits for format index

NVMe format command fields are updated accordingly.

Add a new helper function to fetch the correct format index.
Update examples and unit test files accordingly.

Signed-off-by: default avatarAnkit Kumar <ankit.kumar@samsung.com>
Change-Id: I2d6d9045b9d65ae91cb18843ca75b59cc27ed2f2
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16515


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
parent 4970cd36
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -18,6 +18,11 @@ New function `spdk_env_get_main_core` was added.
New `spdk_nvmf_request_copy_to/from_buf()` APIs have been added, which support
iovecs, unlike the deprecated `spdk_nvmf_request_get_data()`.

### nvme

New API `spdk_nvme_ns_get_format_index` was added to calculate the exact format index, that
was used to format the namespace.

## v23.01

### accel
+9 −6
Original line number Diff line number Diff line
@@ -791,7 +791,7 @@ get_and_print_zns_zone_report(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q
	uint64_t handled_zones = 0;
	uint64_t slba = 0;
	size_t zdes = 0;
	uint32_t zds, zrs;
	uint32_t zds, zrs, format_index;
	int rc = 0;

	outstanding_commands = 0;
@@ -801,7 +801,9 @@ get_and_print_zns_zone_report(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q

	zrs = sizeof(struct spdk_nvme_zns_zone_report);
	zds = sizeof(struct spdk_nvme_zns_zone_desc);
	zdes = nsdata_zns->lbafe[nsdata->flbas.format].zdes * 64;

	format_index = spdk_nvme_ns_get_format_index(nsdata);
	zdes = nsdata_zns->lbafe[format_index].zdes * 64;

	report_bufsize = spdk_nvme_ns_get_max_io_xfer_size(ns);
	report_buf = calloc(1, report_bufsize);
@@ -964,7 +966,7 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
	uint32_t				i;
	uint32_t				flags;
	char					uuid_str[SPDK_UUID_STRING_LEN];
	uint32_t				blocksize;
	uint32_t				blocksize, format_index;
	enum spdk_nvme_dealloc_logical_block_read_value	dlfeat_read_value;

	cdata = spdk_nvme_ctrlr_get_data(ctrlr);
@@ -1017,13 +1019,14 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)
		printf("Protection Information Transferred as: %s\n",
		       nsdata->dps.md_start ? "First 8 Bytes" : "Last 8 Bytes");
	}
	if (nsdata->lbaf[nsdata->flbas.format].ms > 0) {
	format_index = spdk_nvme_ns_get_format_index(nsdata);
	if (nsdata->lbaf[format_index].ms > 0) {
		printf("Metadata Transferred as:               %s\n",
		       nsdata->flbas.extended ? "Extended Data LBA" : "Separate Metadata Buffer");
	}
	printf("Namespace Sharing Capabilities:        %s\n",
	       nsdata->nmic.can_share ? "Multiple Controllers" : "Private");
	blocksize = 1 << nsdata->lbaf[nsdata->flbas.format].lbads;
	blocksize = 1 << nsdata->lbaf[format_index].lbads;
	printf("Size (in LBAs):                        %lld (%lldGiB)\n",
	       (long long)nsdata->nsze,
	       (long long)nsdata->nsze * blocksize / 1024 / 1024 / 1024);
@@ -1103,7 +1106,7 @@ print_namespace(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme_ns *ns)

	printf("Number of LBA Formats:                 %d\n", nsdata->nlbaf + 1);
	printf("Current LBA Format:                    LBA Format #%02d\n",
	       nsdata->flbas.format);
	       format_index);
	for (i = 0; i <= nsdata->nlbaf; i++) {
		printf("LBA Format #%02d: Data Size: %5d  Metadata Size: %5d\n",
		       i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms);
+7 −3
Original line number Diff line number Diff line
@@ -161,8 +161,10 @@ display_namespace(struct spdk_nvme_ns *ns)
{
	const struct spdk_nvme_ns_data		*nsdata;
	uint32_t				i;
	uint32_t				format_index;

	nsdata = spdk_nvme_ns_get_data(ns);
	format_index = spdk_nvme_ns_get_format_index(nsdata);

	printf("Namespace ID:%d\n", spdk_nvme_ns_get_id(ns));

@@ -182,7 +184,7 @@ display_namespace(struct spdk_nvme_ns *ns)
	}
	printf("Number of LBA Formats:       %d\n", nsdata->nlbaf + 1);
	printf("Current LBA Format:          LBA Format #%02d\n",
	       nsdata->flbas.format);
	       format_index);
	for (i = 0; i <= nsdata->nlbaf; i++)
		printf("LBA Format #%02d: Data Size: %5d  Metadata Size: %5d\n",
		       i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms);
@@ -467,7 +469,8 @@ ns_manage_add(struct dev *device, uint64_t ns_size, uint64_t ns_capacity, int ns

	ndata->nsze = ns_size;
	ndata->ncap = ns_capacity;
	ndata->flbas.format = ns_lbasize;
	ndata->flbas.format = ns_lbasize & 0xF;
	ndata->flbas.msb_format = (ns_lbasize >> 4) & 0x3;
	if (SPDK_NVME_FMT_NVM_PROTECTION_DISABLE != ns_dps_type) {
		ndata->dps.pit = ns_dps_type;
		ndata->dps.md_start = ns_dps_location;
@@ -501,11 +504,12 @@ nvme_manage_format(struct dev *device, int ns_id, int ses, int pi, int pil, int
	int ret = 0;
	struct spdk_nvme_format format = {};

	format.lbaf	= lbaf;
	format.lbaf	= lbaf & 0xF;
	format.ms	= ms;
	format.pi	= pi;
	format.pil	= pil;
	format.ses	= ses;
	format.lbafu	= (lbaf >> 4) & 0x3;
	ret = spdk_nvme_ctrlr_format(device->ctrlr, ns_id, &format);
	if (ret) {
		fprintf(stdout, "nvme format: Failed\n");
+12 −0
Original line number Diff line number Diff line
@@ -2851,6 +2851,18 @@ enum spdk_nvme_pi_type spdk_nvme_ns_get_pi_type(struct spdk_nvme_ns *ns);
 */
uint32_t spdk_nvme_ns_get_md_size(struct spdk_nvme_ns *ns);

/**
 * Get the format index of the given namespace.
 *
 * This function is thread safe and can be called at any point while the controller
 * is attached to the SPDK NVMe driver.
 *
 * \param nsdata pointer to the NVMe namespace data.
 *
 * \return the format index of the given namespace.
 */
uint32_t spdk_nvme_ns_get_format_index(const struct spdk_nvme_ns_data *nsdata);

/**
 * Check whether if the namespace can support extended LBA when end-to-end data
 * protection enabled.
+17 −10
Original line number Diff line number Diff line
@@ -2569,9 +2569,12 @@ struct spdk_nvme_ns_data {

	/** formatted lba size */
	struct {
		/** LSB for Format index */
		uint8_t		format     : 4;
		uint8_t		extended   : 1;
		uint8_t		reserved2 : 3;
		/** MSB for Format index, to be ignored if nlbaf <= 16 */
		uint8_t		msb_format : 2;
		uint8_t		reserved2  : 1;
	} flbas;

	/** metadata capabilities */
@@ -2772,9 +2775,7 @@ struct spdk_nvme_ns_data {
		uint32_t	rp	  : 2;

		uint32_t	reserved6 : 6;
	} lbaf[16];

	uint8_t			reserved6[192];
	} lbaf[64];

	uint8_t			vendor_specific[3712];
};
@@ -2835,9 +2836,7 @@ struct spdk_nvme_zns_ns_data {
		uint64_t	zdes : 8;

		uint64_t	reserved15 : 56;
	} lbafe[16];

	uint8_t			reserved3072[768];
	} lbafe[64];

	uint8_t			vendor_specific[256];
};
@@ -3545,13 +3544,21 @@ enum spdk_nvme_metadata_setting {
	SPDK_NVME_FMT_NVM_METADATA_TRANSFER_AS_LBA	= 0x1,
};

/* Format - Command Dword 10 */
struct spdk_nvme_format {
	/* LBA format lower (LSB 4 bits of format index), also called lbafl in 2.0 spec */
	uint32_t	lbaf		: 4;
	/* Metadata settings, also called mset in 2.0 spec */
	uint32_t	ms		: 1;
	/* Protection information */
	uint32_t	pi		: 3;
	/* Protection information location */
	uint32_t	pil		: 1;
	/* Secure erase settings */
	uint32_t	ses		: 3;
	uint32_t	reserved	: 20;
	/* LBA format upper (MSB 2 bits of format index) */
	uint32_t	lbafu		: 2;
	uint32_t	reserved	: 18;
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_format) == 4, "Incorrect size");

Loading