mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
hw/block/nvme: add metadata support
Add support for metadata in the form of extended logical blocks as well as a separate buffer of data. The new `ms` nvme-ns device parameter specifies the size of metadata per logical block in bytes. The `mset` nvme-ns device parameter controls whether metadata is transfered as part of an extended lba (set to '1') or in a separate buffer (set to '0', the default). Regardsless of the scheme chosen with `mset`, metadata is stored at the end of the namespace backing block device. This requires the user provided PRP/SGLs to be walked and "split" into data and metadata scatter/gather lists if the extended logical block scheme is used, but has the advantage of not breaking the deallocated blocks support. Co-authored-by: Gollu Appalanaidu <anaidu.gollu@samsung.com> Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com> Reviewed-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
co-authored by
Gollu Appalanaidu
parent
3754df04ec
commit
bc3a65e992
+17
-3
@@ -37,13 +37,25 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
|
||||
BlockDriverInfo bdi;
|
||||
NvmeIdNs *id_ns = &ns->id_ns;
|
||||
int lba_index = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas);
|
||||
int npdg;
|
||||
int npdg, nlbas;
|
||||
|
||||
ns->id_ns.dlfeat = 0x9;
|
||||
|
||||
id_ns->lbaf[lba_index].ds = 31 - clz32(ns->blkconf.logical_block_size);
|
||||
id_ns->lbaf[lba_index].ms = ns->params.ms;
|
||||
|
||||
id_ns->nsze = cpu_to_le64(nvme_ns_nlbas(ns));
|
||||
if (ns->params.ms) {
|
||||
id_ns->mc = 0x3;
|
||||
|
||||
if (ns->params.mset) {
|
||||
id_ns->flbas |= 0x10;
|
||||
}
|
||||
}
|
||||
|
||||
nlbas = nvme_ns_nlbas(ns);
|
||||
|
||||
id_ns->nsze = cpu_to_le64(nlbas);
|
||||
ns->mdata_offset = nvme_l2b(ns, nlbas);
|
||||
|
||||
ns->csi = NVME_CSI_NVM;
|
||||
|
||||
@@ -140,7 +152,7 @@ static int nvme_ns_zoned_check_calc_geometry(NvmeNamespace *ns, Error **errp)
|
||||
*/
|
||||
ns->zone_size = zone_size / lbasz;
|
||||
ns->zone_capacity = zone_cap / lbasz;
|
||||
ns->num_zones = ns->size / lbasz / ns->zone_size;
|
||||
ns->num_zones = nvme_ns_nlbas(ns) / ns->zone_size;
|
||||
|
||||
/* Do a few more sanity checks of ZNS properties */
|
||||
if (!ns->num_zones) {
|
||||
@@ -402,6 +414,8 @@ static Property nvme_ns_props[] = {
|
||||
DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false),
|
||||
DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0),
|
||||
DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid),
|
||||
DEFINE_PROP_UINT16("ms", NvmeNamespace, params.ms, 0),
|
||||
DEFINE_PROP_UINT8("mset", NvmeNamespace, params.mset, 0),
|
||||
DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
|
||||
DEFINE_PROP_UINT32("mcl", NvmeNamespace, params.mcl, 128),
|
||||
DEFINE_PROP_UINT8("msrc", NvmeNamespace, params.msrc, 127),
|
||||
|
||||
+33
-6
@@ -30,6 +30,9 @@ typedef struct NvmeNamespaceParams {
|
||||
uint32_t nsid;
|
||||
QemuUUID uuid;
|
||||
|
||||
uint16_t ms;
|
||||
uint8_t mset;
|
||||
|
||||
uint16_t mssrl;
|
||||
uint32_t mcl;
|
||||
uint8_t msrc;
|
||||
@@ -48,6 +51,7 @@ typedef struct NvmeNamespace {
|
||||
BlockConf blkconf;
|
||||
int32_t bootindex;
|
||||
int64_t size;
|
||||
int64_t mdata_offset;
|
||||
NvmeIdNs id_ns;
|
||||
const uint32_t *iocs;
|
||||
uint8_t csi;
|
||||
@@ -101,18 +105,41 @@ static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns)
|
||||
return nvme_ns_lbaf(ns)->ds;
|
||||
}
|
||||
|
||||
/* calculate the number of LBAs that the namespace can accomodate */
|
||||
static inline uint64_t nvme_ns_nlbas(NvmeNamespace *ns)
|
||||
{
|
||||
return ns->size >> nvme_ns_lbads(ns);
|
||||
}
|
||||
|
||||
/* convert an LBA to the equivalent in bytes */
|
||||
static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
|
||||
{
|
||||
return lba << nvme_ns_lbads(ns);
|
||||
}
|
||||
|
||||
static inline size_t nvme_lsize(NvmeNamespace *ns)
|
||||
{
|
||||
return 1 << nvme_ns_lbads(ns);
|
||||
}
|
||||
|
||||
static inline uint16_t nvme_msize(NvmeNamespace *ns)
|
||||
{
|
||||
return nvme_ns_lbaf(ns)->ms;
|
||||
}
|
||||
|
||||
static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba)
|
||||
{
|
||||
return nvme_msize(ns) * lba;
|
||||
}
|
||||
|
||||
static inline bool nvme_ns_ext(NvmeNamespace *ns)
|
||||
{
|
||||
return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas);
|
||||
}
|
||||
|
||||
/* calculate the number of LBAs that the namespace can accomodate */
|
||||
static inline uint64_t nvme_ns_nlbas(NvmeNamespace *ns)
|
||||
{
|
||||
if (ns->params.ms) {
|
||||
return ns->size / (nvme_lsize(ns) + nvme_msize(ns));
|
||||
}
|
||||
return ns->size >> nvme_ns_lbads(ns);
|
||||
}
|
||||
|
||||
typedef struct NvmeCtrl NvmeCtrl;
|
||||
|
||||
static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone)
|
||||
|
||||
+578
-83
File diff suppressed because it is too large
Load Diff
@@ -44,16 +44,19 @@ pci_nvme_flush(uint16_t cid, uint32_t nsid) "cid %"PRIu16" nsid %"PRIu32""
|
||||
pci_nvme_read(uint16_t cid, uint32_t nsid, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" nsid %"PRIu32" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64""
|
||||
pci_nvme_write(uint16_t cid, const char *verb, uint32_t nsid, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" opname '%s' nsid %"PRIu32" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64""
|
||||
pci_nvme_rw_cb(uint16_t cid, const char *blkname) "cid %"PRIu16" blk '%s'"
|
||||
pci_nvme_misc_cb(uint16_t cid, const char *blkname) "cid %"PRIu16" blk '%s'"
|
||||
pci_nvme_copy(uint16_t cid, uint32_t nsid, uint16_t nr, uint8_t format) "cid %"PRIu16" nsid %"PRIu32" nr %"PRIu16" format 0x%"PRIx8""
|
||||
pci_nvme_copy_source_range(uint64_t slba, uint32_t nlb) "slba 0x%"PRIx64" nlb %"PRIu32""
|
||||
pci_nvme_copy_in_complete(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_copy_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_rw_complete_cb(uint16_t cid, const char *blkname) "cid %"PRIu16" blk '%s'"
|
||||
pci_nvme_block_status(int64_t offset, int64_t bytes, int64_t pnum, int ret, bool zeroed) "offset %"PRId64" bytes %"PRId64" pnum %"PRId64" ret 0x%x zeroed %d"
|
||||
pci_nvme_dsm(uint16_t cid, uint32_t nsid, uint32_t nr, uint32_t attr) "cid %"PRIu16" nsid %"PRIu32" nr %"PRIu32" attr 0x%"PRIx32""
|
||||
pci_nvme_dsm_deallocate(uint16_t cid, uint32_t nsid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" nsid %"PRIu32" slba %"PRIu64" nlb %"PRIu32""
|
||||
pci_nvme_dsm_single_range_limit_exceeded(uint32_t nlb, uint32_t dmrsl) "nlb %"PRIu32" dmrsl %"PRIu32""
|
||||
pci_nvme_compare(uint16_t cid, uint32_t nsid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" nsid %"PRIu32" slba 0x%"PRIx64" nlb %"PRIu32""
|
||||
pci_nvme_compare_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_compare_data_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_compare_mdata_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aio_discard_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aio_copy_in_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aio_zone_reset_cb(uint16_t cid, uint64_t zslba) "cid %"PRIu16" zslba 0x%"PRIx64""
|
||||
|
||||
Reference in New Issue
Block a user