Allow namespace to enable pass-through of protection information between guest and integrity capable BlockBackend.
Signed-off-by: Dmitry Tihov <d.ti...@yadro.com> --- hw/nvme/ns.c | 59 +++++++++++++++++++++++++++++++++++++++++++++----- hw/nvme/nvme.h | 2 ++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index 62a1f97be0..da0cff71f8 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -35,7 +35,11 @@ void nvme_ns_init_format(NvmeNamespace *ns) ns->lbaf = id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; ns->lbasz = 1 << ns->lbaf.ds; - nlbas = ns->size / (ns->lbasz + ns->lbaf.ms); + if (ns->pip) { + nlbas = ns->size / (ns->lbasz); + } else { + nlbas = ns->size / (ns->lbasz + ns->lbaf.ms); + } id_ns->nsze = cpu_to_le64(nlbas); @@ -60,17 +64,22 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) static uint64_t ns_count; NvmeIdNs *id_ns = &ns->id_ns; NvmeIdNsNvm *id_ns_nvm = &ns->id_ns_nvm; + BlockDriverInfo bdi; uint8_t ds; uint16_t ms; - int i; + int i, ret; + + ns->pip = ns->params.pip; ns->csi = NVME_CSI_NVM; ns->status = 0x0; ns->id_ns.dlfeat = 0x1; - /* support DULBE and I/O optimization fields */ - id_ns->nsfeat |= (0x4 | 0x10); + if (!ns->pip) { + /* support DULBE and I/O optimization fields */ + id_ns->nsfeat |= (0x4 | 0x10); + } if (ns->params.shared) { id_ns->nmic |= NVME_NMIC_NS_SHARED; @@ -89,7 +98,11 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) id_ns->eui64 = cpu_to_be64(ns->params.eui64); ds = 31 - clz32(ns->blkconf.logical_block_size); - ms = ns->params.ms; + if (ns->pip) { + ms = 8; + } else { + ms = ns->params.ms; + } id_ns->mc = NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE; @@ -105,6 +118,14 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp) ns->pif = ns->params.pif; + if (ns->pip) { + ret = bdrv_get_info(blk_bs(ns->blkconf.blk), &bdi); + if (ret >= 0) { + id_ns->dps = bdi.protection_type; + ns->pif = NVME_PI_GUARD_16; + } + } + static const NvmeLBAF lbaf[16] = { [0] = { .ds = 9 }, [1] = { .ds = 9, .ms = 8 }, @@ -380,13 +401,38 @@ static void nvme_zoned_ns_shutdown(NvmeNamespace *ns) static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp) { unsigned int pi_size; + BlockDriverInfo bdi; + int ret; if (!ns->blkconf.blk) { error_setg(errp, "block backend not configured"); return -1; } - if (ns->params.pi) { + if (ns->params.pip) { + if (ns->params.mset) { + error_setg(errp, "invalid mset parameter, metadata must be " + "stored in a separate buffer to use integrity passthrough"); + return -1; + } + ret = bdrv_get_info(blk_bs(ns->blkconf.blk), &bdi); + if (ret < 0) { + error_setg(errp, "could not determine host block device" + " integrity information"); + return -1; + } + if (!bdi.protection_type) { + error_setg(errp, "nvme-ns backend block device does not" + " support integrity passthrough"); + return -1; + } + if (bdi.protection_interval != ns->blkconf.logical_block_size) { + error_setg(errp, "logical block size parameter (%u bytes) must be" + " equal to protection information interval (%u bytes)", + ns->blkconf.logical_block_size, bdi.protection_interval); + return -1; + } + } else if (ns->params.pi) { if (ns->params.pi > NVME_ID_NS_DPS_TYPE_3) { error_setg(errp, "invalid 'pi' value"); return -1; @@ -623,6 +669,7 @@ static Property nvme_ns_props[] = { DEFINE_PROP_UINT8("pi", NvmeNamespace, params.pi, 0), DEFINE_PROP_UINT8("pil", NvmeNamespace, params.pil, 0), DEFINE_PROP_UINT8("pif", NvmeNamespace, params.pif, 0), + DEFINE_PROP_BOOL("pip", NvmeNamespace, params.pip, false), DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128), DEFINE_PROP_UINT32("mcl", NvmeNamespace, params.mcl, 128), DEFINE_PROP_UINT8("msrc", NvmeNamespace, params.msrc, 127), diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 79f5c281c2..4876670d26 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -109,6 +109,7 @@ typedef struct NvmeNamespaceParams { uint8_t pi; uint8_t pil; uint8_t pif; + bool pip; uint16_t mssrl; uint32_t mcl; @@ -143,6 +144,7 @@ typedef struct NvmeNamespace { uint16_t status; int attached; uint8_t pif; + bool pip; struct { uint16_t zrwas; -- 2.38.1