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:
parent
4970cd36df
commit
7bbeb80a31
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user