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: Ankit Kumar <ankit.kumar@samsung.com>
Change-Id: I2d6d9045b9d65ae91cb18843ca75b59cc27ed2f2
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16515
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
This commit is contained in:
Ankit Kumar 2023-01-26 04:04:30 +05:30 committed by Tomasz Zawadzki
parent 4970cd36df
commit 7bbeb80a31
14 changed files with 87 additions and 25 deletions

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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.

View File

@ -2569,9 +2569,12 @@ struct spdk_nvme_ns_data {
/** formatted lba size */
struct {
uint8_t format : 4;
uint8_t extended : 1;
uint8_t reserved2 : 3;
/** LSB for Format index */
uint8_t format : 4;
uint8_t extended : 1;
/** 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");

View File

@ -21,15 +21,17 @@ void
nvme_ns_set_identify_data(struct spdk_nvme_ns *ns)
{
struct spdk_nvme_ns_data *nsdata;
uint32_t format_index;
nsdata = _nvme_ns_get_data(ns);
ns->flags = 0x0000;
format_index = spdk_nvme_ns_get_format_index(nsdata);
ns->sector_size = 1 << nsdata->lbaf[nsdata->flbas.format].lbads;
ns->sector_size = 1 << nsdata->lbaf[format_index].lbads;
ns->extended_lba_size = ns->sector_size;
ns->md_size = nsdata->lbaf[nsdata->flbas.format].ms;
ns->md_size = nsdata->lbaf[format_index].ms;
if (nsdata->flbas.extended) {
ns->flags |= SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED;
ns->extended_lba_size += ns->md_size;
@ -80,7 +82,7 @@ nvme_ns_set_identify_data(struct spdk_nvme_ns *ns)
}
ns->pi_type = SPDK_NVME_FMT_NVM_PROTECTION_DISABLE;
if (nsdata->lbaf[nsdata->flbas.format].ms && nsdata->dps.pit) {
if (nsdata->lbaf[format_index].ms && nsdata->dps.pit) {
ns->flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
ns->pi_type = nsdata->dps.pit;
}
@ -318,6 +320,16 @@ spdk_nvme_ns_get_md_size(struct spdk_nvme_ns *ns)
return ns->md_size;
}
uint32_t
spdk_nvme_ns_get_format_index(const struct spdk_nvme_ns_data *nsdata)
{
if (nsdata->nlbaf < 16) {
return nsdata->flbas.format;
} else {
return ((nsdata->flbas.msb_format << 4) + nsdata->flbas.format);
}
}
const struct spdk_nvme_ns_data *
spdk_nvme_ns_get_data(struct spdk_nvme_ns *ns)
{

View File

@ -17,8 +17,11 @@ spdk_nvme_zns_ns_get_zone_size_sectors(struct spdk_nvme_ns *ns)
{
const struct spdk_nvme_zns_ns_data *nsdata_zns = spdk_nvme_zns_ns_get_data(ns);
const struct spdk_nvme_ns_data *nsdata = spdk_nvme_ns_get_data(ns);
uint32_t format_index;
return nsdata_zns->lbafe[nsdata->flbas.format].zsze;
format_index = spdk_nvme_ns_get_format_index(nsdata);
return nsdata_zns->lbafe[format_index].zsze;
}
uint64_t

View File

@ -136,6 +136,7 @@
spdk_nvme_ns_get_size;
spdk_nvme_ns_get_pi_type;
spdk_nvme_ns_get_md_size;
spdk_nvme_ns_get_format_index;
spdk_nvme_ns_supports_extended_lba;
spdk_nvme_ns_supports_compare;
spdk_nvme_ns_get_dealloc_logical_block_read_value;

View File

@ -2618,7 +2618,7 @@ spdk_nvmf_ctrlr_identify_ns(struct spdk_nvmf_ctrlr *ctrlr,
{
struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
struct spdk_nvmf_ns *ns;
uint32_t max_num_blocks;
uint32_t max_num_blocks, format_index;
enum spdk_nvme_ana_state ana_state;
ns = _nvmf_subsystem_get_ns_safe(subsystem, cmd->nsid, rsp);
@ -2629,9 +2629,12 @@ spdk_nvmf_ctrlr_identify_ns(struct spdk_nvmf_ctrlr *ctrlr,
nvmf_bdev_ctrlr_identify_ns(ns, nsdata, ctrlr->dif_insert_or_strip);
assert(ctrlr->admin_qpair);
format_index = spdk_nvme_ns_get_format_index(nsdata);
/* Due to bug in the Linux kernel NVMe driver we have to set noiob no larger than mdts */
max_num_blocks = ctrlr->admin_qpair->transport->opts.max_io_size /
(1U << nsdata->lbaf[nsdata->flbas.format].lbads);
(1U << nsdata->lbaf[format_index].lbads);
if (nsdata->noiob > max_num_blocks) {
nsdata->noiob = max_num_blocks;
}

View File

@ -129,6 +129,7 @@ nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *n
nsdata->nuse = num_blocks;
nsdata->nlbaf = 0;
nsdata->flbas.format = 0;
nsdata->flbas.msb_format = 0;
nsdata->nacwu = spdk_bdev_get_acwu(bdev) - 1; /* nacwu is 0-based */
if (!dif_insert_or_strip) {
nsdata->lbaf[0].ms = spdk_bdev_get_md_size(bdev);

View File

@ -253,6 +253,7 @@ test_nvme_ns_set_identify_data(void)
ns.nsdata.nsrescap.raw = 1;
ns.nsdata.dps.pit = SPDK_NVME_FMT_NVM_PROTECTION_TYPE1;
ns.nsdata.flbas.format = 0;
ns.nsdata.flbas.msb_format = 0;
ns.nsdata.lbaf[0].lbads = 9;
ns.nsdata.lbaf[0].ms = 8;

View File

@ -210,6 +210,9 @@ DEFINE_STUB(spdk_bdev_get_max_open_zones, uint32_t, (const struct spdk_bdev *bde
DEFINE_STUB(spdk_bdev_get_zone_size, uint64_t, (const struct spdk_bdev *bdev), ZONE_SIZE);
DEFINE_STUB(spdk_bdev_is_zoned, bool, (const struct spdk_bdev *bdev), false);
DEFINE_STUB(spdk_nvme_ns_get_format_index, uint32_t,
(const struct spdk_nvme_ns_data *nsdata), 0);
int
spdk_nvmf_qpair_disconnect(struct spdk_nvmf_qpair *qpair, nvmf_qpair_disconnect_cb cb_fn, void *ctx)
{
@ -229,6 +232,7 @@ nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *n
nsdata->nuse = num_blocks;
nsdata->nlbaf = 0;
nsdata->flbas.format = 0;
nsdata->flbas.msb_format = 0;
nsdata->lbaf[0].lbads = spdk_u32log2(512);
}

View File

@ -488,6 +488,7 @@ test_nvmf_bdev_ctrlr_identify_ns(void)
CU_ASSERT(nsdata.nuse == 10);
CU_ASSERT(nsdata.nlbaf == 0);
CU_ASSERT(nsdata.flbas.format == 0);
CU_ASSERT(nsdata.flbas.msb_format == 0);
CU_ASSERT(nsdata.nacwu == 0);
CU_ASSERT(nsdata.lbaf[0].lbads == spdk_u32log2(4096));
CU_ASSERT(nsdata.lbaf[0].ms == 512);
@ -516,6 +517,7 @@ test_nvmf_bdev_ctrlr_identify_ns(void)
CU_ASSERT(nsdata.nuse == 10);
CU_ASSERT(nsdata.nlbaf == 0);
CU_ASSERT(nsdata.flbas.format == 0);
CU_ASSERT(nsdata.flbas.msb_format == 0);
CU_ASSERT(nsdata.nacwu == 0);
CU_ASSERT(nsdata.lbaf[0].lbads == spdk_u32log2(4096));
CU_ASSERT(nsdata.noiob == SPDK_BDEV_IO_NUM_CHILD_IOV);

View File

@ -235,6 +235,9 @@ DEFINE_STUB(spdk_bdev_get_max_open_zones, uint32_t,
DEFINE_STUB(spdk_bdev_is_zoned, bool, (const struct spdk_bdev *bdev), false);
DEFINE_STUB(spdk_bdev_get_zone_size, uint64_t, (const struct spdk_bdev *bdev), 0);
DEFINE_STUB(spdk_nvme_ns_get_format_index, uint32_t,
(const struct spdk_nvme_ns_data *nsdata), 0);
struct spdk_io_channel *
spdk_accel_get_io_channel(void)
{
@ -339,6 +342,7 @@ nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *n
nsdata->nuse = num_blocks;
nsdata->nlbaf = 0;
nsdata->flbas.format = 0;
nsdata->flbas.msb_format = 0;
nsdata->lbaf[0].lbads = spdk_u32log2(512);
}