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
{
47 uint64_t zone_size_bs
;
49 uint32_t max_active_zones
;
50 uint32_t max_open_zones
;
51 uint32_t zd_extension_size
;
52 } NvmeNamespaceParams
;
54 typedef struct NvmeNamespace
{
55 DeviceState parent_obj
;
66 QTAILQ_ENTRY(NvmeNamespace
) entry
;
68 NvmeIdNsZoned
*id_ns_zoned
;
70 QTAILQ_HEAD(, NvmeZone
) exp_open_zones
;
71 QTAILQ_HEAD(, NvmeZone
) imp_open_zones
;
72 QTAILQ_HEAD(, NvmeZone
) closed_zones
;
73 QTAILQ_HEAD(, NvmeZone
) full_zones
;
76 uint64_t zone_capacity
;
77 uint32_t zone_size_log2
;
78 uint8_t *zd_extensions
;
79 int32_t nr_open_zones
;
80 int32_t nr_active_zones
;
82 NvmeNamespaceParams params
;
89 static inline uint16_t nvme_ns_status(NvmeNamespace
*ns
)
94 static inline uint32_t nvme_nsid(NvmeNamespace
*ns
)
97 return ns
->params
.nsid
;
103 static inline NvmeLBAF
*nvme_ns_lbaf(NvmeNamespace
*ns
)
105 NvmeIdNs
*id_ns
= &ns
->id_ns
;
106 return &id_ns
->lbaf
[NVME_ID_NS_FLBAS_INDEX(id_ns
->flbas
)];
109 static inline uint8_t nvme_ns_lbads(NvmeNamespace
*ns
)
111 return nvme_ns_lbaf(ns
)->ds
;
114 /* convert an LBA to the equivalent in bytes */
115 static inline size_t nvme_l2b(NvmeNamespace
*ns
, uint64_t lba
)
117 return lba
<< nvme_ns_lbads(ns
);
120 static inline size_t nvme_lsize(NvmeNamespace
*ns
)
122 return 1 << nvme_ns_lbads(ns
);
125 static inline uint16_t nvme_msize(NvmeNamespace
*ns
)
127 return nvme_ns_lbaf(ns
)->ms
;
130 static inline size_t nvme_m2b(NvmeNamespace
*ns
, uint64_t lba
)
132 return nvme_msize(ns
) * lba
;
135 static inline bool nvme_ns_ext(NvmeNamespace
*ns
)
137 return !!NVME_ID_NS_FLBAS_EXTENDED(ns
->id_ns
.flbas
);
140 /* calculate the number of LBAs that the namespace can accomodate */
141 static inline uint64_t nvme_ns_nlbas(NvmeNamespace
*ns
)
143 if (nvme_msize(ns
)) {
144 return ns
->size
/ (nvme_lsize(ns
) + nvme_msize(ns
));
146 return ns
->size
>> nvme_ns_lbads(ns
);
149 typedef struct NvmeCtrl NvmeCtrl
;
151 static inline NvmeZoneState
nvme_get_zone_state(NvmeZone
*zone
)
153 return zone
->d
.zs
>> 4;
156 static inline void nvme_set_zone_state(NvmeZone
*zone
, NvmeZoneState state
)
158 zone
->d
.zs
= state
<< 4;
161 static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace
*ns
, NvmeZone
*zone
)
163 return zone
->d
.zslba
+ ns
->zone_size
;
166 static inline uint64_t nvme_zone_wr_boundary(NvmeZone
*zone
)
168 return zone
->d
.zslba
+ zone
->d
.zcap
;
171 static inline bool nvme_wp_is_valid(NvmeZone
*zone
)
173 uint8_t st
= nvme_get_zone_state(zone
);
175 return st
!= NVME_ZONE_STATE_FULL
&&
176 st
!= NVME_ZONE_STATE_READ_ONLY
&&
177 st
!= NVME_ZONE_STATE_OFFLINE
;
180 static inline uint8_t *nvme_get_zd_extension(NvmeNamespace
*ns
,
183 return &ns
->zd_extensions
[zone_idx
* ns
->params
.zd_extension_size
];
186 static inline void nvme_aor_inc_open(NvmeNamespace
*ns
)
188 assert(ns
->nr_open_zones
>= 0);
189 if (ns
->params
.max_open_zones
) {
191 assert(ns
->nr_open_zones
<= ns
->params
.max_open_zones
);
195 static inline void nvme_aor_dec_open(NvmeNamespace
*ns
)
197 if (ns
->params
.max_open_zones
) {
198 assert(ns
->nr_open_zones
> 0);
201 assert(ns
->nr_open_zones
>= 0);
204 static inline void nvme_aor_inc_active(NvmeNamespace
*ns
)
206 assert(ns
->nr_active_zones
>= 0);
207 if (ns
->params
.max_active_zones
) {
208 ns
->nr_active_zones
++;
209 assert(ns
->nr_active_zones
<= ns
->params
.max_active_zones
);
213 static inline void nvme_aor_dec_active(NvmeNamespace
*ns
)
215 if (ns
->params
.max_active_zones
) {
216 assert(ns
->nr_active_zones
> 0);
217 ns
->nr_active_zones
--;
218 assert(ns
->nr_active_zones
>= ns
->nr_open_zones
);
220 assert(ns
->nr_active_zones
>= 0);
223 void nvme_ns_init_format(NvmeNamespace
*ns
);
224 int nvme_ns_setup(NvmeCtrl
*n
, NvmeNamespace
*ns
, Error
**errp
);
225 void nvme_ns_drain(NvmeNamespace
*ns
);
226 void nvme_ns_shutdown(NvmeNamespace
*ns
);
227 void nvme_ns_cleanup(NvmeNamespace
*ns
);
229 #endif /* NVME_NS_H */