diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index f05d85075f08..966fba605d79 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -4616,10 +4616,10 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req,
                 continue;
             }
         }
-        if (ns->params.nsid <= min_nsid) {
+        if (ns->nsid <= min_nsid) {
             continue;
         }
-        list_ptr[j++] = cpu_to_le32(ns->params.nsid);
+        list_ptr[j++] = cpu_to_le32(ns->nsid);
         if (j == data_len / sizeof(uint32_t)) {
             break;
         }
@@ -4664,10 +4664,10 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req,
                 continue;
             }
         }
-        if (ns->params.nsid <= min_nsid || c->csi != ns->csi) {
+        if (ns->nsid <= min_nsid || c->csi != ns->csi) {
             continue;
         }
-        list_ptr[j++] = cpu_to_le32(ns->params.nsid);
+        list_ptr[j++] = cpu_to_le32(ns->nsid);
         if (j == data_len / sizeof(uint32_t)) {
             break;
         }
@@ -4714,14 +4714,14 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req)
      */
     uuid.hdr.nidt = NVME_NIDT_UUID;
     uuid.hdr.nidl = NVME_NIDL_UUID;
-    memcpy(uuid.v, ns->params.uuid.data, NVME_NIDL_UUID);
+    memcpy(uuid.v, ns->uuid.data, NVME_NIDL_UUID);
     memcpy(pos, &uuid, sizeof(uuid));
     pos += sizeof(uuid);
 
-    if (ns->params.eui64) {
+    if (ns->eui64.v) {
         eui64.hdr.nidt = NVME_NIDT_EUI64;
         eui64.hdr.nidl = NVME_NIDL_EUI64;
-        eui64.v = cpu_to_be64(ns->params.eui64);
+        eui64.v = cpu_to_be64(ns->eui64.v);
         memcpy(pos, &eui64, sizeof(eui64));
         pos += sizeof(eui64);
     }
@@ -5260,7 +5260,7 @@ static uint16_t nvme_ns_attachment(NvmeCtrl *n, NvmeRequest *req)
                 return NVME_NS_ALREADY_ATTACHED | NVME_DNR;
             }
 
-            if (ns->attached && !ns->params.shared) {
+            if (ns->attached && !(ns->flags & NVME_NS_SHARED)) {
                 return NVME_NS_PRIVATE | NVME_DNR;
             }
 
@@ -5338,12 +5338,12 @@ static void nvme_format_set(NvmeNamespace *ns, NvmeCmd *cmd)
     uint8_t mset = (dw10 >> 4) & 0x1;
     uint8_t pil = (dw10 >> 8) & 0x1;
 
-    trace_pci_nvme_format_set(ns->params.nsid, lbaf, mset, pi, pil);
+    trace_pci_nvme_format_set(ns->nsid, lbaf, mset, pi, pil);
 
     nvm->id_ns.dps = (pil << 3) | pi;
     nvm->id_ns.flbas = lbaf | (mset << 4);
 
-    nvme_ns_init_format(ns);
+    nvme_ns_nvm_init_format(nvm);
 }
 
 static void nvme_format_ns_cb(void *opaque, int ret)
@@ -6544,7 +6544,7 @@ static int nvme_init_subsys(NvmeCtrl *n, Error **errp)
 void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns)
 {
     NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns);
-    uint32_t nsid = ns->params.nsid;
+    uint32_t nsid = ns->nsid;
     assert(nsid && nsid <= NVME_MAX_NAMESPACES);
 
     n->namespaces[nsid] = ns;
@@ -6557,7 +6557,6 @@ void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns)
 static void nvme_realize(PCIDevice *pci_dev, Error **errp)
 {
     NvmeCtrl *n = NVME(pci_dev);
-    NvmeNamespace *ns;
     Error *local_err = NULL;
 
     nvme_check_constraints(n, &local_err);
@@ -6582,12 +6581,11 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
 
     /* setup a namespace if the controller drive property was given */
     if (n->namespace.blkconf.blk) {
-        ns = &n->namespace;
-        ns->params.nsid = 1;
+        NvmeNamespaceDevice *nsdev = &n->namespace;
+        NvmeNamespace *ns = &nsdev->ns;
+        ns->nsid = 1;
 
-        if (nvme_ns_setup(ns, errp)) {
-            return;
-        }
+        nvme_ns_init(ns);
 
         nvme_attach_ns(n, ns);
     }
diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index 0e231102c475..b411b184c253 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -26,9 +26,8 @@
 
 #define MIN_DISCARD_GRANULARITY (4 * KiB)
 
-void nvme_ns_init_format(NvmeNamespace *ns)
+void nvme_ns_nvm_init_format(NvmeNamespaceNvm *nvm)
 {
-    NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns);
     NvmeIdNs *id_ns = &nvm->id_ns;
     BlockDriverInfo bdi;
     int npdg, nlbas, ret;
@@ -48,7 +47,7 @@ void nvme_ns_init_format(NvmeNamespace *ns)
 
     npdg = nvm->discard_granularity / nvm->lbasz;
 
-    ret = bdrv_get_info(blk_bs(ns->blkconf.blk), &bdi);
+    ret = bdrv_get_info(blk_bs(nvm->blk), &bdi);
     if (ret >= 0 && bdi.cluster_size > nvm->discard_granularity) {
         npdg = bdi.cluster_size / nvm->lbasz;
     }
@@ -56,53 +55,39 @@ void nvme_ns_init_format(NvmeNamespace *ns)
     id_ns->npda = id_ns->npdg = npdg - 1;
 }
 
-static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
+void nvme_ns_init(NvmeNamespace *ns)
 {
     NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns);
-    static uint64_t ns_count;
     NvmeIdNs *id_ns = &nvm->id_ns;
     uint8_t ds;
     uint16_t ms;
     int i;
 
-    ns->csi = NVME_CSI_NVM;
-    ns->status = 0x0;
-
-    nvm->id_ns.dlfeat = 0x1;
+    id_ns->dlfeat = 0x1;
 
     /* support DULBE and I/O optimization fields */
     id_ns->nsfeat |= (0x4 | 0x10);
 
-    if (ns->params.shared) {
+    if (ns->flags & NVME_NS_SHARED) {
         id_ns->nmic |= NVME_NMIC_NS_SHARED;
     }
 
-    /* Substitute a missing EUI-64 by an autogenerated one */
-    ++ns_count;
-    if (!ns->params.eui64 && ns->params.eui64_default) {
-        ns->params.eui64 = ns_count + NVME_EUI64_DEFAULT;
-    }
-
     /* simple copy */
     id_ns->mssrl = cpu_to_le16(nvm->mssrl);
     id_ns->mcl = cpu_to_le32(nvm->mcl);
     id_ns->msrc = nvm->msrc;
-    id_ns->eui64 = cpu_to_be64(ns->params.eui64);
+    id_ns->eui64 = cpu_to_be64(ns->eui64.v);
 
     ds = 31 - clz32(nvm->lbasz);
-    ms = ns->params.ms;
+    ms = nvm->lbaf.ms;
 
     id_ns->mc = NVME_ID_NS_MC_EXTENDED | NVME_ID_NS_MC_SEPARATE;
 
-    if (ms && ns->params.mset) {
+    if (ms && nvm->flags & NVME_NS_NVM_EXTENDED_LBA) {
         id_ns->flbas |= NVME_ID_NS_FLBAS_EXTENDED;
     }
 
     id_ns->dpc = 0x1f;
-    id_ns->dps = ns->params.pi;
-    if (ns->params.pi && ns->params.pil) {
-        id_ns->dps |= NVME_ID_NS_DPS_FIRST_EIGHT;
-    }
 
     static const NvmeLBAF lbaf[16] = {
         [0] = { .ds =  9           },
@@ -135,59 +120,63 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
     id_ns->flbas |= id_ns->nlbaf;
 
 lbaf_found:
-    nvme_ns_init_format(ns);
-
-    return 0;
+    nvme_ns_nvm_init_format(nvm);
 }
 
-static int nvme_ns_init_blk(NvmeNamespace *ns, Error **errp)
+static int nvme_nsdev_init_blk(NvmeNamespaceDevice *nsdev,
+                               Error **errp)
 {
+    NvmeNamespace *ns = &nsdev->ns;
     NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns);
+    BlockConf *blkconf = &nsdev->blkconf;
     bool read_only;
 
-    if (!blkconf_blocksizes(&ns->blkconf, errp)) {
+    if (!blkconf_blocksizes(blkconf, errp)) {
         return -1;
     }
 
-    read_only = !blk_supports_write_perm(ns->blkconf.blk);
-    if (!blkconf_apply_backend_options(&ns->blkconf, read_only, false, errp)) {
+    read_only = !blk_supports_write_perm(blkconf->blk);
+    if (!blkconf_apply_backend_options(blkconf, read_only, false, errp)) {
         return -1;
     }
 
-    if (ns->blkconf.discard_granularity == -1) {
-        ns->blkconf.discard_granularity =
-            MAX(ns->blkconf.logical_block_size, MIN_DISCARD_GRANULARITY);
+    if (blkconf->discard_granularity == -1) {
+        blkconf->discard_granularity =
+            MAX(blkconf->logical_block_size, MIN_DISCARD_GRANULARITY);
     }
 
-    nvm->lbasz = ns->blkconf.logical_block_size;
-    nvm->discard_granularity = ns->blkconf.discard_granularity;
+    nvm->lbasz = blkconf->logical_block_size;
+    nvm->discard_granularity = blkconf->discard_granularity;
     nvm->lbaf.ds = 31 - clz32(nvm->lbasz);
-    nvm->lbaf.ms = ns->params.ms;
+    nvm->lbaf.ms = nsdev->params.ms;
+    nvm->blk = blkconf->blk;
 
-    nvm->size = blk_getlength(ns->blkconf.blk);
+    nvm->size = blk_getlength(nvm->blk);
     if (nvm->size < 0) {
-        error_setg_errno(errp, -nvm->size, "could not get blockdev size");
+        error_setg_errno(errp, -(nvm->size), "could not get blockdev size");
         return -1;
     }
 
     return 0;
 }
 
-static int nvme_ns_zoned_check_calc_geometry(NvmeNamespace *ns, Error **errp)
+static int nvme_nsdev_zoned_check_calc_geometry(NvmeNamespaceDevice *nsdev,
+                                                Error **errp)
 {
+    NvmeNamespace *ns = &nsdev->ns;
     NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(ns);
     NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns);
 
     uint64_t zone_size, zone_cap;
 
     /* Make sure that the values of ZNS properties are sane */
-    if (ns->params.zone_size_bs) {
-        zone_size = ns->params.zone_size_bs;
+    if (nsdev->params.zone_size_bs) {
+        zone_size = nsdev->params.zone_size_bs;
     } else {
         zone_size = NVME_DEFAULT_ZONE_SIZE;
     }
-    if (ns->params.zone_cap_bs) {
-        zone_cap = ns->params.zone_cap_bs;
+    if (nsdev->params.zone_cap_bs) {
+        zone_cap = nsdev->params.zone_cap_bs;
     } else {
         zone_cap = zone_size;
     }
@@ -359,46 +348,47 @@ static void nvme_ns_zoned_shutdown(NvmeNamespaceZoned *zoned)
     assert(zoned->nr_open_zones == 0);
 }
 
-static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp)
+static int nvme_nsdev_check_constraints(NvmeNamespaceDevice *nsdev,
+                                        Error **errp)
 {
-    if (!ns->blkconf.blk) {
+    if (!nsdev->blkconf.blk) {
         error_setg(errp, "block backend not configured");
         return -1;
     }
 
-    if (ns->params.pi && ns->params.ms < 8) {
+    if (nsdev->params.pi && nsdev->params.ms < 8) {
         error_setg(errp, "at least 8 bytes of metadata required to enable "
                    "protection information");
         return -1;
     }
 
-    if (ns->params.nsid > NVME_MAX_NAMESPACES) {
+    if (nsdev->params.nsid > NVME_MAX_NAMESPACES) {
         error_setg(errp, "invalid namespace id (must be between 0 and %d)",
                    NVME_MAX_NAMESPACES);
         return -1;
     }
 
-    if (ns->params.zoned) {
-        if (ns->params.max_active_zones) {
-            if (ns->params.max_open_zones > ns->params.max_active_zones) {
+    if (nsdev->params.zoned) {
+        if (nsdev->params.max_active_zones) {
+            if (nsdev->params.max_open_zones > nsdev->params.max_active_zones) {
                 error_setg(errp, "max_open_zones (%u) exceeds "
-                           "max_active_zones (%u)", ns->params.max_open_zones,
-                           ns->params.max_active_zones);
+                           "max_active_zones (%u)", nsdev->params.max_open_zones,
+                           nsdev->params.max_active_zones);
                 return -1;
             }
 
-            if (!ns->params.max_open_zones) {
-                ns->params.max_open_zones = ns->params.max_active_zones;
+            if (!nsdev->params.max_open_zones) {
+                nsdev->params.max_open_zones = nsdev->params.max_active_zones;
             }
         }
 
-        if (ns->params.zd_extension_size) {
-            if (ns->params.zd_extension_size & 0x3f) {
+        if (nsdev->params.zd_extension_size) {
+            if (nsdev->params.zd_extension_size & 0x3f) {
                 error_setg(errp, "zone descriptor extension size must be a "
                            "multiple of 64B");
                 return -1;
             }
-            if ((ns->params.zd_extension_size >> 6) > 0xff) {
+            if ((nsdev->params.zd_extension_size >> 6) > 0xff) {
                 error_setg(errp,
                            "zone descriptor extension size is too large");
                 return -1;
@@ -409,35 +399,57 @@ static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp)
     return 0;
 }
 
-int nvme_ns_setup(NvmeNamespace *ns, Error **errp)
+static int nvme_nsdev_setup(NvmeNamespaceDevice *nsdev, Error **errp)
 {
-    if (nvme_ns_check_constraints(ns, errp)) {
+    NvmeNamespaceNvm *nvm = NVME_NAMESPACE_NVM(&nsdev->ns);
+    static uint64_t ns_count;
+
+    if (nvme_nsdev_check_constraints(nsdev, errp)) {
         return -1;
     }
 
-    if (nvme_ns_init_blk(ns, errp)) {
-        return -1;
+    if (nsdev->params.shared) {
+        nsdev->ns.flags |= NVME_NS_SHARED;
     }
 
-    if (nvme_ns_init(ns, errp)) {
-        return -1;
-    }
-    if (ns->params.zoned) {
-        NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(ns);
+    nsdev->ns.nsid = nsdev->params.nsid;
+    memcpy(&nsdev->ns.uuid, &nsdev->params.uuid, sizeof(nsdev->ns.uuid));
 
-        if (nvme_ns_zoned_check_calc_geometry(ns, errp) != 0) {
+    if (nsdev->params.eui64) {
+        stq_be_p(&nsdev->ns.eui64.v, nsdev->params.eui64);
+    }
+
+    /* Substitute a missing EUI-64 by an autogenerated one */
+    ++ns_count;
+    if (!nsdev->ns.eui64.v && nsdev->params.eui64_default) {
+        nsdev->ns.eui64.v = ns_count + NVME_EUI64_DEFAULT;
+    }
+
+    nvm->id_ns.dps = nsdev->params.pi;
+    if (nsdev->params.pi && nsdev->params.pil) {
+        nvm->id_ns.dps |= NVME_ID_NS_DPS_FIRST_EIGHT;
+    }
+
+    nsdev->ns.csi = NVME_CSI_NVM;
+
+    nvme_ns_init(&nsdev->ns);
+
+    if (nsdev->params.zoned) {
+        NvmeNamespaceZoned *zoned = NVME_NAMESPACE_ZONED(&nsdev->ns);
+
+        if (nvme_nsdev_zoned_check_calc_geometry(nsdev, errp) != 0) {
             return -1;
         }
 
         /* copy device parameters */
-        zoned->zd_extension_size = ns->params.zd_extension_size;
-        zoned->max_open_zones = ns->params.max_open_zones;
-        zoned->max_active_zones = ns->params.max_open_zones;
-        if (ns->params.cross_zone_read) {
+        zoned->zd_extension_size = nsdev->params.zd_extension_size;
+        zoned->max_open_zones = nsdev->params.max_open_zones;
+        zoned->max_active_zones = nsdev->params.max_open_zones;
+        if (nsdev->params.cross_zone_read) {
             zoned->flags |= NVME_NS_ZONED_CROSS_READ;
         }
 
-        nvme_ns_zoned_init(ns);
+        nvme_ns_zoned_init(&nsdev->ns);
     }
 
     return 0;
@@ -445,12 +457,12 @@ int nvme_ns_setup(NvmeNamespace *ns, Error **errp)
 
 void nvme_ns_drain(NvmeNamespace *ns)
 {
-    blk_drain(ns->blkconf.blk);
+    blk_drain(nvme_blk(ns));
 }
 
 void nvme_ns_shutdown(NvmeNamespace *ns)
 {
-    blk_flush(ns->blkconf.blk);
+    blk_flush(nvme_blk(ns));
     if (nvme_ns_zoned(ns)) {
         nvme_ns_zoned_shutdown(NVME_NAMESPACE_ZONED(ns));
     }
@@ -466,32 +478,34 @@ void nvme_ns_cleanup(NvmeNamespace *ns)
     }
 }
 
-static void nvme_ns_unrealize(DeviceState *dev)
+static void nvme_nsdev_unrealize(DeviceState *dev)
 {
-    NvmeNamespace *ns = NVME_NS(dev);
+    NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev);
+    NvmeNamespace *ns = &nsdev->ns;
 
     nvme_ns_drain(ns);
     nvme_ns_shutdown(ns);
     nvme_ns_cleanup(ns);
 }
 
-static void nvme_ns_realize(DeviceState *dev, Error **errp)
+static void nvme_nsdev_realize(DeviceState *dev, Error **errp)
 {
-    NvmeNamespace *ns = NVME_NS(dev);
+    NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(dev);
+    NvmeNamespace *ns = &nsdev->ns;
     BusState *s = qdev_get_parent_bus(dev);
     NvmeCtrl *n = NVME(s->parent);
     NvmeSubsystem *subsys = n->subsys;
-    uint32_t nsid = ns->params.nsid;
+    uint32_t nsid = nsdev->params.nsid;
     int i;
 
     if (!n->subsys) {
-        if (ns->params.detached) {
+        if (nsdev->params.detached) {
             error_setg(errp, "detached requires that the nvme device is "
                        "linked to an nvme-subsys device");
             return;
         }
 
-        if (ns->params.shared) {
+        if (nsdev->params.shared) {
             error_setg(errp, "shared requires that the nvme device is "
                        "linked to an nvme-subsys device");
             return;
@@ -506,7 +520,11 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
         }
     }
 
-    if (nvme_ns_setup(ns, errp)) {
+    if (nvme_nsdev_init_blk(nsdev, errp)) {
+        return;
+    }
+
+    if (nvme_nsdev_setup(nsdev, errp)) {
         return;
     }
 
@@ -516,7 +534,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
                 continue;
             }
 
-            nsid = ns->params.nsid = i;
+            nsid = ns->nsid = i;
             break;
         }
 
@@ -534,11 +552,11 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
     if (subsys) {
         subsys->namespaces[nsid] = ns;
 
-        if (ns->params.detached) {
+        if (nsdev->params.detached) {
             return;
         }
 
-        if (ns->params.shared) {
+        if (nsdev->params.shared) {
             for (i = 0; i < ARRAY_SIZE(subsys->ctrls); i++) {
                 NvmeCtrl *ctrl = subsys->ctrls[i];
 
@@ -554,73 +572,74 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
     nvme_attach_ns(n, ns);
 }
 
-static Property nvme_ns_props[] = {
-    DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf),
-    DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false),
-    DEFINE_PROP_BOOL("shared", NvmeNamespace, params.shared, false),
-    DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0),
-    DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid),
-    DEFINE_PROP_UINT64("eui64", NvmeNamespace, params.eui64, 0),
-    DEFINE_PROP_UINT16("ms", NvmeNamespace, params.ms, 0),
-    DEFINE_PROP_UINT8("mset", NvmeNamespace, params.mset, 0),
-    DEFINE_PROP_UINT8("pi", NvmeNamespace, params.pi, 0),
-    DEFINE_PROP_UINT8("pil", NvmeNamespace, params.pil, 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),
-    DEFINE_PROP_BOOL("zoned", NvmeNamespace, params.zoned, false),
-    DEFINE_PROP_SIZE("zoned.zone_size", NvmeNamespace, params.zone_size_bs,
+static Property nvme_nsdev_props[] = {
+    DEFINE_BLOCK_PROPERTIES(NvmeNamespaceDevice, blkconf),
+    DEFINE_PROP_BOOL("detached", NvmeNamespaceDevice, params.detached, false),
+    DEFINE_PROP_BOOL("shared", NvmeNamespaceDevice, params.shared, false),
+    DEFINE_PROP_UINT32("nsid", NvmeNamespaceDevice, params.nsid, 0),
+    DEFINE_PROP_UUID("uuid", NvmeNamespaceDevice, params.uuid),
+    DEFINE_PROP_UINT64("eui64", NvmeNamespaceDevice, params.eui64, 0),
+    DEFINE_PROP_UINT16("ms", NvmeNamespaceDevice, params.ms, 0),
+    DEFINE_PROP_UINT8("mset", NvmeNamespaceDevice, params.mset, 0),
+    DEFINE_PROP_UINT8("pi", NvmeNamespaceDevice, params.pi, 0),
+    DEFINE_PROP_UINT8("pil", NvmeNamespaceDevice, params.pil, 0),
+    DEFINE_PROP_UINT16("mssrl", NvmeNamespaceDevice, params.mssrl, 128),
+    DEFINE_PROP_UINT32("mcl", NvmeNamespaceDevice, params.mcl, 128),
+    DEFINE_PROP_UINT8("msrc", NvmeNamespaceDevice, params.msrc, 127),
+    DEFINE_PROP_BOOL("zoned", NvmeNamespaceDevice, params.zoned, false),
+    DEFINE_PROP_SIZE("zoned.zone_size", NvmeNamespaceDevice, params.zone_size_bs,
                      NVME_DEFAULT_ZONE_SIZE),
-    DEFINE_PROP_SIZE("zoned.zone_capacity", NvmeNamespace, params.zone_cap_bs,
+    DEFINE_PROP_SIZE("zoned.zone_capacity", NvmeNamespaceDevice, params.zone_cap_bs,
                      0),
-    DEFINE_PROP_BOOL("zoned.cross_read", NvmeNamespace,
+    DEFINE_PROP_BOOL("zoned.cross_read", NvmeNamespaceDevice,
                      params.cross_zone_read, false),
-    DEFINE_PROP_UINT32("zoned.max_active", NvmeNamespace,
+    DEFINE_PROP_UINT32("zoned.max_active", NvmeNamespaceDevice,
                        params.max_active_zones, 0),
-    DEFINE_PROP_UINT32("zoned.max_open", NvmeNamespace,
+    DEFINE_PROP_UINT32("zoned.max_open", NvmeNamespaceDevice,
                        params.max_open_zones, 0),
-    DEFINE_PROP_UINT32("zoned.descr_ext_size", NvmeNamespace,
+    DEFINE_PROP_UINT32("zoned.descr_ext_size", NvmeNamespaceDevice,
                        params.zd_extension_size, 0),
-    DEFINE_PROP_BOOL("eui64-default", NvmeNamespace, params.eui64_default,
+    DEFINE_PROP_BOOL("eui64-default", NvmeNamespaceDevice, params.eui64_default,
                      true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void nvme_ns_class_init(ObjectClass *oc, void *data)
+static void nvme_nsdev_class_init(ObjectClass *oc, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
 
     dc->bus_type = TYPE_NVME_BUS;
-    dc->realize = nvme_ns_realize;
-    dc->unrealize = nvme_ns_unrealize;
-    device_class_set_props(dc, nvme_ns_props);
+    dc->realize = nvme_nsdev_realize;
+    dc->unrealize = nvme_nsdev_unrealize;
+    device_class_set_props(dc, nvme_nsdev_props);
     dc->desc = "Virtual NVMe namespace";
 }
 
-static void nvme_ns_instance_init(Object *obj)
+static void nvme_nsdev_instance_init(Object *obj)
 {
-    NvmeNamespace *ns = NVME_NS(obj);
-    char *bootindex = g_strdup_printf("/namespace@%d,0", ns->params.nsid);
+    NvmeNamespaceDevice *nsdev = NVME_NAMESPACE_DEVICE(obj);
+    char *bootindex = g_strdup_printf("/namespace@%d,0",
+                                      nsdev->params.nsid);
 
-    device_add_bootindex_property(obj, &ns->bootindex, "bootindex",
+    device_add_bootindex_property(obj, &nsdev->bootindex, "bootindex",
                                   bootindex, DEVICE(obj));
 
     g_free(bootindex);
 }
 
-static const TypeInfo nvme_ns_info = {
-    .name = TYPE_NVME_NS,
+static const TypeInfo nvme_nsdev_info = {
+    .name = TYPE_NVME_NAMESPACE_DEVICE,
     .parent = TYPE_DEVICE,
-    .class_init = nvme_ns_class_init,
-    .instance_size = sizeof(NvmeNamespace),
-    .instance_init = nvme_ns_instance_init,
+    .class_init = nvme_nsdev_class_init,
+    .instance_size = sizeof(NvmeNamespaceDevice),
+    .instance_init = nvme_nsdev_instance_init,
 };
 
-static void nvme_ns_register_types(void)
+static void register_types(void)
 {
-    type_register_static(&nvme_ns_info);
+    type_register_static(&nvme_nsdev_info);
 }
 
-type_init(nvme_ns_register_types)
+type_init(register_types)
diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h
index 525bfd0ca831..4ae4b4e5ffe1 100644
--- a/hw/nvme/nvme.h
+++ b/hw/nvme/nvme.h
@@ -80,9 +80,8 @@ static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
     return subsys->namespaces[nsid];
 }
 
-#define TYPE_NVME_NS "nvme-ns"
-#define NVME_NS(obj) \
-    OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
+#define TYPE_NVME_NAMESPACE_DEVICE "nvme-ns"
+OBJECT_DECLARE_SIMPLE_TYPE(NvmeNamespaceDevice, NVME_NAMESPACE_DEVICE)
 
 typedef struct NvmeNamespaceParams {
     bool     detached;
@@ -170,19 +169,26 @@ typedef struct NvmeNamespaceNvm {
     unsigned long flags;
 } NvmeNamespaceNvm;
 
+enum NvmeNamespaceFlags {
+    NVME_NS_SHARED = 1 << 0,
+};
+
 typedef struct NvmeNamespace {
-    DeviceState  parent_obj;
-    BlockConf    blkconf;
-    int32_t      bootindex;
+    uint32_t nsid;
+    uint8_t  csi;
+    QemuUUID uuid;
+    union {
+        uint64_t v;
+        uint8_t  a[8];
+    } eui64;
+    NvmeNGUID nguid;
+
+    unsigned long flags;
+
     const uint32_t *iocs;
-    uint8_t      csi;
     uint16_t     status;
     int          attached;
 
-    QTAILQ_ENTRY(NvmeNamespace) entry;
-
-    NvmeNamespaceParams params;
-
     struct {
         uint32_t err_rec;
     } features;
@@ -199,10 +205,19 @@ static inline BlockBackend *nvme_blk(NvmeNamespace *ns)
     return NVME_NAMESPACE_NVM(ns)->blk;
 }
 
+typedef struct NvmeNamespaceDevice {
+    DeviceState  parent_obj;
+    BlockConf    blkconf;
+    int32_t      bootindex;
+
+    NvmeNamespace       ns;
+    NvmeNamespaceParams params;
+} NvmeNamespaceDevice;
+
 static inline uint32_t nvme_nsid(NvmeNamespace *ns)
 {
     if (ns) {
-        return ns->params.nsid;
+        return ns->nsid;
     }
 
     return 0;
@@ -228,8 +243,8 @@ static inline bool nvme_ns_ext(NvmeNamespaceNvm *nvm)
     return !!NVME_ID_NS_FLBAS_EXTENDED(nvm->id_ns.flbas);
 }
 
-void nvme_ns_init_format(NvmeNamespace *ns);
-int nvme_ns_setup(NvmeNamespace *ns, Error **errp);
+void nvme_ns_nvm_init_format(NvmeNamespaceNvm *nvm);
+void nvme_ns_init(NvmeNamespace *ns);
 void nvme_ns_drain(NvmeNamespace *ns);
 void nvme_ns_shutdown(NvmeNamespace *ns);
 void nvme_ns_cleanup(NvmeNamespace *ns);
@@ -424,7 +439,7 @@ typedef struct NvmeCtrl {
 
     NvmeSubsystem   *subsys;
 
-    NvmeNamespace   namespace;
+    NvmeNamespaceDevice namespace;
     NvmeNamespace   *namespaces[NVME_MAX_NAMESPACES + 1];
     NvmeSQueue      **sq;
     NvmeCQueue      **cq;
