2 * QEMU NVM Express Virtual Namespace
4 * Copyright (c) 2019 CNEX Labs
5 * Copyright (c) 2020 Samsung Electronics
8 * Klaus Jensen <k.jensen@samsung.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See the
11 * COPYING file in the top-level directory.
18 #include "qemu/uuid.h"
20 #define TYPE_NVME_NS "nvme-ns"
21 #define NVME_NS(obj) \
22 OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
24 typedef struct NvmeZone
{
27 QTAILQ_ENTRY(NvmeZone
) entry
;
30 typedef struct NvmeNamespaceParams
{
46 uint64_t zone_size_bs
;
48 uint32_t max_active_zones
;
49 uint32_t max_open_zones
;
50 uint32_t zd_extension_size
;
51 } NvmeNamespaceParams
;
53 typedef struct NvmeNamespace
{
54 DeviceState parent_obj
;
64 NvmeSubsystem
*subsys
;
65 QTAILQ_ENTRY(NvmeNamespace
) entry
;
67 NvmeIdNsZoned
*id_ns_zoned
;
69 QTAILQ_HEAD(, NvmeZone
) exp_open_zones
;
70 QTAILQ_HEAD(, NvmeZone
) imp_open_zones
;
71 QTAILQ_HEAD(, NvmeZone
) closed_zones
;
72 QTAILQ_HEAD(, NvmeZone
) full_zones
;
75 uint64_t zone_capacity
;
76 uint32_t zone_size_log2
;
77 uint8_t *zd_extensions
;
78 int32_t nr_open_zones
;
79 int32_t nr_active_zones
;
81 NvmeNamespaceParams params
;
88 static inline uint16_t nvme_ns_status(NvmeNamespace
*ns
)
93 static inline uint32_t nvme_nsid(NvmeNamespace
*ns
)
96 return ns
->params
.nsid
;
102 static inline bool nvme_ns_shared(NvmeNamespace
*ns
)
107 static inline NvmeLBAF
*nvme_ns_lbaf(NvmeNamespace
*ns
)
109 NvmeIdNs
*id_ns
= &ns
->id_ns
;
110 return &id_ns
->lbaf
[NVME_ID_NS_FLBAS_INDEX(id_ns
->flbas
)];
113 static inline uint8_t nvme_ns_lbads(NvmeNamespace
*ns
)
115 return nvme_ns_lbaf(ns
)->ds
;
118 /* convert an LBA to the equivalent in bytes */
119 static inline size_t nvme_l2b(NvmeNamespace
*ns
, uint64_t lba
)
121 return lba
<< nvme_ns_lbads(ns
);
124 static inline size_t nvme_lsize(NvmeNamespace
*ns
)
126 return 1 << nvme_ns_lbads(ns
);
129 static inline uint16_t nvme_msize(NvmeNamespace
*ns
)
131 return nvme_ns_lbaf(ns
)->ms
;
134 static inline size_t nvme_m2b(NvmeNamespace
*ns
, uint64_t lba
)
136 return nvme_msize(ns
) * lba
;
139 static inline bool nvme_ns_ext(NvmeNamespace
*ns
)
141 return !!NVME_ID_NS_FLBAS_EXTENDED(ns
->id_ns
.flbas
);
144 /* calculate the number of LBAs that the namespace can accomodate */
145 static inline uint64_t nvme_ns_nlbas(NvmeNamespace
*ns
)
147 if (nvme_msize(ns
)) {
148 return ns
->size
/ (nvme_lsize(ns
) + nvme_msize(ns
));
150 return ns
->size
>> nvme_ns_lbads(ns
);
153 typedef struct NvmeCtrl NvmeCtrl
;
155 static inline NvmeZoneState
nvme_get_zone_state(NvmeZone
*zone
)
157 return zone
->d
.zs
>> 4;
160 static inline void nvme_set_zone_state(NvmeZone
*zone
, NvmeZoneState state
)
162 zone
->d
.zs
= state
<< 4;
165 static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace
*ns
, NvmeZone
*zone
)
167 return zone
->d
.zslba
+ ns
->zone_size
;
170 static inline uint64_t nvme_zone_wr_boundary(NvmeZone
*zone
)
172 return zone
->d
.zslba
+ zone
->d
.zcap
;
175 static inline bool nvme_wp_is_valid(NvmeZone
*zone
)
177 uint8_t st
= nvme_get_zone_state(zone
);
179 return st
!= NVME_ZONE_STATE_FULL
&&
180 st
!= NVME_ZONE_STATE_READ_ONLY
&&
181 st
!= NVME_ZONE_STATE_OFFLINE
;
184 static inline uint8_t *nvme_get_zd_extension(NvmeNamespace
*ns
,
187 return &ns
->zd_extensions
[zone_idx
* ns
->params
.zd_extension_size
];
190 static inline void nvme_aor_inc_open(NvmeNamespace
*ns
)
192 assert(ns
->nr_open_zones
>= 0);
193 if (ns
->params
.max_open_zones
) {
195 assert(ns
->nr_open_zones
<= ns
->params
.max_open_zones
);
199 static inline void nvme_aor_dec_open(NvmeNamespace
*ns
)
201 if (ns
->params
.max_open_zones
) {
202 assert(ns
->nr_open_zones
> 0);
205 assert(ns
->nr_open_zones
>= 0);
208 static inline void nvme_aor_inc_active(NvmeNamespace
*ns
)
210 assert(ns
->nr_active_zones
>= 0);
211 if (ns
->params
.max_active_zones
) {
212 ns
->nr_active_zones
++;
213 assert(ns
->nr_active_zones
<= ns
->params
.max_active_zones
);
217 static inline void nvme_aor_dec_active(NvmeNamespace
*ns
)
219 if (ns
->params
.max_active_zones
) {
220 assert(ns
->nr_active_zones
> 0);
221 ns
->nr_active_zones
--;
222 assert(ns
->nr_active_zones
>= ns
->nr_open_zones
);
224 assert(ns
->nr_active_zones
>= 0);
227 void nvme_ns_init_format(NvmeNamespace
*ns
);
228 int nvme_ns_setup(NvmeNamespace
*ns
, Error
**errp
);
229 void nvme_ns_drain(NvmeNamespace
*ns
);
230 void nvme_ns_shutdown(NvmeNamespace
*ns
);
231 void nvme_ns_cleanup(NvmeNamespace
*ns
);
233 #endif /* NVME_NS_H */