On Wed, 2020-09-30 at 07:59 +0200, Klaus Jensen wrote: > On Sep 28 11:35, Dmitry Fomichev wrote: > > The emulation code has been changed to advertise NVM Command Set when > > "zoned" device property is not set (default) and Zoned Namespace > > Command Set otherwise. > > > > Handlers for three new NVMe commands introduced in Zoned Namespace > > Command Set specification are added, namely for Zone Management > > Receive, Zone Management Send and Zone Append. > > > > Device initialization code has been extended to create a proper > > configuration for zoned operation using device properties. > > > > Read/Write command handler is modified to only allow writes at the > > write pointer if the namespace is zoned. For Zone Append command, > > writes implicitly happen at the write pointer and the starting write > > pointer value is returned as the result of the command. Write Zeroes > > handler is modified to add zoned checks that are identical to those > > done as a part of Write flow. > > > > The code to support for Zone Descriptor Extensions is not included in > > this commit and ZDES 0 is always reported. A later commit in this > > series will add ZDE support. > > > > This commit doesn't yet include checks for active and open zone > > limits. It is assumed that there are no limits on either active or > > open zones. > > > > Signed-off-by: Niklas Cassel <niklas.cas...@wdc.com> > > Signed-off-by: Hans Holmberg <hans.holmb...@wdc.com> > > Signed-off-by: Ajay Joshi <ajay.jo...@wdc.com> > > Signed-off-by: Chaitanya Kulkarni <chaitanya.kulka...@wdc.com> > > Signed-off-by: Matias Bjorling <matias.bjorl...@wdc.com> > > Signed-off-by: Aravind Ramesh <aravind.ram...@wdc.com> > > Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawas...@wdc.com> > > Signed-off-by: Adam Manzanares <adam.manzana...@wdc.com> > > Signed-off-by: Dmitry Fomichev <dmitry.fomic...@wdc.com> > > --- > > block/nvme.c | 2 +- > > hw/block/nvme-ns.c | 185 ++++++++- > > hw/block/nvme-ns.h | 6 +- > > hw/block/nvme.c | 872 +++++++++++++++++++++++++++++++++++++++++-- > > include/block/nvme.h | 6 +- > > 5 files changed, 1033 insertions(+), 38 deletions(-) > > > > diff --git a/block/nvme.c b/block/nvme.c > > index 05485fdd11..7a513c9a17 100644 > > --- a/block/nvme.c > > +++ b/block/nvme.c > > +static int nvme_calc_zone_geometry(NvmeNamespace *ns, Error **errp) > > +{ > > + uint64_t zone_size, zone_cap; > > + uint32_t nz, lbasz = ns->blkconf.logical_block_size; > > + > > + if (ns->params.zone_size_mb) { > > + zone_size = ns->params.zone_size_mb; > > + } else { > > + zone_size = NVME_DEFAULT_ZONE_SIZE; > > + } > > + if (ns->params.zone_capacity_mb) { > > + zone_cap = ns->params.zone_capacity_mb; > > + } else { > > + zone_cap = zone_size; > > + } > > I think a check that zone_capacity_mb is less than or equal to > zone_size_mb is missing earlier?
The check is right below, but I now think it is better to compare byte sizes rather than numbers of LBAs. There are also checks missing for zone_size >= lbasz and zone_cap >= lbasz that I am adding. > > > +static int nvme_zoned_init_ns(NvmeCtrl *n, NvmeNamespace *ns, int > > lba_index, > > + Error **errp) > > +{ > > + NvmeIdNsZoned *id_ns_z; > > + > > + if (n->params.fill_pattern == 0) { > > + ns->id_ns.dlfeat |= 0x01; > > + } else if (n->params.fill_pattern == 0xff) { > > + ns->id_ns.dlfeat |= 0x02; > > + } > > + > > + if (nvme_calc_zone_geometry(ns, errp) != 0) { > > + return -1; > > + } > > + > > + nvme_init_zone_meta(ns); > > + > > + id_ns_z = g_malloc0(sizeof(NvmeIdNsZoned)); > > + > > + /* MAR/MOR are zeroes-based, 0xffffffff means no limit */ > > + id_ns_z->mar = 0xffffffff; > > + id_ns_z->mor = 0xffffffff; > > + id_ns_z->zoc = 0; > > + id_ns_z->ozcs = ns->params.cross_zone_read ? 0x01 : 0x00; > > + > > + id_ns_z->lbafe[lba_index].zsze = cpu_to_le64(ns->zone_size); > > + id_ns_z->lbafe[lba_index].zdes = 0; /* FIXME make helper */ > > + > > + ns->csi = NVME_CSI_ZONED; > > + ns->id_ns.ncap = cpu_to_le64(ns->zone_capacity * ns->num_zones); > > + ns->id_ns.nuse = ns->id_ns.ncap; > > + ns->id_ns.nsze = ns->id_ns.ncap; > > + > > NSZE should be in terms of ZSZE. We *can* report NCAP < NSZE if zcap != > zsze, but that requires bit 1 set in NSFEAT and proper reporting of > NUSE. Ok, will correct. I think it used to be this way, but got messed up during multiple transformations of this code. > > > @@ -133,6 +304,14 @@ static void nvme_ns_realize(DeviceState *dev, Error > > **errp) > > static Property nvme_ns_props[] = { > > DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf), > > DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0), > > + > > + DEFINE_PROP_BOOL("zoned", NvmeNamespace, params.zoned, false), > > + DEFINE_PROP_UINT64("zone_size", NvmeNamespace, params.zone_size_mb, > > + NVME_DEFAULT_ZONE_SIZE), > > + DEFINE_PROP_UINT64("zone_capacity", NvmeNamespace, > > + params.zone_capacity_mb, 0), > > There is a nice DEFINE_PROP_SIZE that handles sizes in a nice way (i.e. > 1G, 1M). It should be nice to use these types, will add them. _SIZE32 sounds like a good candidate to use for ZASL. Thank you for your valuable feedback! >