Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2015 Intel Corporation. All rights reserved.
3 : * Copyright (c) 2020, 2021 Mellanox Technologies LTD. All rights reserved.
4 : */
5 :
6 : #include "nvme_internal.h"
7 :
8 : static inline struct spdk_nvme_ns_data *
9 58 : _nvme_ns_get_data(struct spdk_nvme_ns *ns)
10 : {
11 58 : return &ns->nsdata;
12 : }
13 :
14 : /**
15 : * Update Namespace flags based on Identify Controller
16 : * and Identify Namespace. This can be also used for
17 : * Namespace Attribute Notice events and Namespace
18 : * operations such as Attach/Detach.
19 : */
20 : void
21 13 : nvme_ns_set_identify_data(struct spdk_nvme_ns *ns)
22 : {
23 : struct spdk_nvme_ns_data *nsdata;
24 : struct spdk_nvme_nvm_ns_data *nsdata_nvm;
25 : uint32_t format_index;
26 :
27 13 : nsdata = _nvme_ns_get_data(ns);
28 13 : nsdata_nvm = ns->nsdata_nvm;
29 :
30 13 : ns->flags = 0x0000;
31 13 : format_index = spdk_nvme_ns_get_format_index(nsdata);
32 :
33 13 : ns->sector_size = 1 << nsdata->lbaf[format_index].lbads;
34 13 : ns->extended_lba_size = ns->sector_size;
35 :
36 13 : ns->md_size = nsdata->lbaf[format_index].ms;
37 13 : if (nsdata->flbas.extended) {
38 2 : ns->flags |= SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED;
39 2 : ns->extended_lba_size += ns->md_size;
40 : }
41 :
42 13 : ns->sectors_per_max_io = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->extended_lba_size;
43 13 : ns->sectors_per_max_io_no_md = spdk_nvme_ns_get_max_io_xfer_size(ns) / ns->sector_size;
44 13 : if (ns->ctrlr->quirks & NVME_QUIRK_MDTS_EXCLUDE_MD) {
45 1 : ns->sectors_per_max_io = ns->sectors_per_max_io_no_md;
46 : }
47 :
48 13 : if (nsdata->noiob) {
49 2 : ns->sectors_per_stripe = nsdata->noiob;
50 2 : SPDK_DEBUGLOG(nvme, "ns %u optimal IO boundary %" PRIu32 " blocks\n",
51 : ns->id, ns->sectors_per_stripe);
52 11 : } else if (ns->ctrlr->quirks & NVME_INTEL_QUIRK_STRIPING &&
53 0 : ns->ctrlr->cdata.vs[3] != 0) {
54 0 : ns->sectors_per_stripe = (1ULL << ns->ctrlr->cdata.vs[3]) * ns->ctrlr->min_page_size /
55 0 : ns->sector_size;
56 0 : SPDK_DEBUGLOG(nvme, "ns %u stripe size quirk %" PRIu32 " blocks\n",
57 : ns->id, ns->sectors_per_stripe);
58 : } else {
59 11 : ns->sectors_per_stripe = 0;
60 : }
61 :
62 13 : if (ns->ctrlr->cdata.oncs.dsm) {
63 2 : ns->flags |= SPDK_NVME_NS_DEALLOCATE_SUPPORTED;
64 : }
65 :
66 13 : if (ns->ctrlr->cdata.oncs.compare) {
67 2 : ns->flags |= SPDK_NVME_NS_COMPARE_SUPPORTED;
68 : }
69 :
70 13 : if (ns->ctrlr->cdata.vwc.present) {
71 2 : ns->flags |= SPDK_NVME_NS_FLUSH_SUPPORTED;
72 : }
73 :
74 13 : if (ns->ctrlr->cdata.oncs.write_zeroes) {
75 2 : ns->flags |= SPDK_NVME_NS_WRITE_ZEROES_SUPPORTED;
76 : }
77 :
78 13 : if (ns->ctrlr->cdata.oncs.write_unc) {
79 2 : ns->flags |= SPDK_NVME_NS_WRITE_UNCORRECTABLE_SUPPORTED;
80 : }
81 :
82 13 : if (nsdata->nsrescap.raw) {
83 2 : ns->flags |= SPDK_NVME_NS_RESERVATION_SUPPORTED;
84 : }
85 :
86 13 : ns->pi_type = SPDK_NVME_FMT_NVM_PROTECTION_DISABLE;
87 13 : if (nsdata->lbaf[format_index].ms && nsdata->dps.pit) {
88 2 : ns->flags |= SPDK_NVME_NS_DPS_PI_SUPPORTED;
89 2 : ns->pi_type = nsdata->dps.pit;
90 2 : if (nsdata_nvm != NULL && ns->ctrlr->cdata.ctratt.bits.elbas) {
91 : /* We may have nsdata_nvm for other purposes but
92 : * the elbaf array is only valid when elbas is 1.
93 : */
94 0 : ns->pi_format = nsdata_nvm->elbaf[format_index].pif;
95 : } else {
96 2 : ns->pi_format = SPDK_NVME_16B_GUARD_PI;
97 : }
98 : }
99 13 : }
100 :
101 : static int
102 11 : nvme_ctrlr_identify_ns(struct spdk_nvme_ns *ns)
103 : {
104 : struct nvme_completion_poll_status *status;
105 : struct spdk_nvme_ns_data *nsdata;
106 : int rc;
107 :
108 11 : status = calloc(1, sizeof(*status));
109 11 : if (!status) {
110 0 : SPDK_ERRLOG("Failed to allocate status tracker\n");
111 0 : return -ENOMEM;
112 : }
113 :
114 11 : nsdata = _nvme_ns_get_data(ns);
115 11 : rc = nvme_ctrlr_cmd_identify(ns->ctrlr, SPDK_NVME_IDENTIFY_NS, 0, ns->id, 0,
116 : nsdata, sizeof(*nsdata),
117 : nvme_completion_poll_cb, status);
118 11 : if (rc != 0) {
119 0 : free(status);
120 0 : return rc;
121 : }
122 :
123 11 : if (nvme_wait_for_completion_robust_lock(ns->ctrlr->adminq, status,
124 11 : &ns->ctrlr->ctrlr_lock)) {
125 0 : if (!status->timed_out) {
126 0 : free(status);
127 : }
128 : /* This can occur if the namespace is not active. Simply zero the
129 : * namespace data and continue. */
130 0 : nvme_ns_destruct(ns);
131 0 : return 0;
132 : }
133 11 : free(status);
134 :
135 11 : nvme_ns_set_identify_data(ns);
136 :
137 11 : return 0;
138 : }
139 :
140 : static int
141 1 : nvme_ctrlr_identify_ns_zns_specific(struct spdk_nvme_ns *ns)
142 : {
143 : struct nvme_completion_poll_status *status;
144 1 : struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr;
145 : struct spdk_nvme_zns_ns_data *nsdata_zns;
146 : int rc;
147 :
148 1 : nvme_ns_free_zns_specific_data(ns);
149 :
150 1 : nsdata_zns = spdk_zmalloc(sizeof(*nsdata_zns), 64, NULL, SPDK_ENV_NUMA_ID_ANY,
151 : SPDK_MALLOC_SHARE);
152 1 : if (!nsdata_zns) {
153 0 : return -ENOMEM;
154 : }
155 :
156 1 : status = calloc(1, sizeof(*status));
157 1 : if (!status) {
158 0 : SPDK_ERRLOG("Failed to allocate status tracker\n");
159 0 : spdk_free(nsdata_zns);
160 0 : return -ENOMEM;
161 : }
162 :
163 1 : rc = nvme_ctrlr_cmd_identify(ctrlr, SPDK_NVME_IDENTIFY_NS_IOCS, 0, ns->id, ns->csi,
164 : nsdata_zns, sizeof(*nsdata_zns),
165 : nvme_completion_poll_cb, status);
166 1 : if (rc != 0) {
167 0 : spdk_free(nsdata_zns);
168 0 : free(status);
169 0 : return rc;
170 : }
171 :
172 1 : if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
173 0 : SPDK_ERRLOG("Failed to retrieve Identify IOCS Specific Namespace Data Structure\n");
174 0 : spdk_free(nsdata_zns);
175 0 : if (!status->timed_out) {
176 0 : free(status);
177 : }
178 0 : return -ENXIO;
179 : }
180 1 : free(status);
181 1 : ns->nsdata_zns = nsdata_zns;
182 :
183 1 : return 0;
184 : }
185 :
186 : static int
187 1 : nvme_ctrlr_identify_ns_nvm_specific(struct spdk_nvme_ns *ns)
188 : {
189 : struct nvme_completion_poll_status *status;
190 1 : struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr;
191 : struct spdk_nvme_nvm_ns_data *nsdata_nvm;
192 : int rc;
193 :
194 1 : nvme_ns_free_zns_specific_data(ns);
195 :
196 1 : nsdata_nvm = spdk_zmalloc(sizeof(*nsdata_nvm), 64, NULL, SPDK_ENV_NUMA_ID_ANY,
197 : SPDK_MALLOC_SHARE);
198 1 : if (!nsdata_nvm) {
199 0 : return -ENOMEM;
200 : }
201 :
202 1 : status = calloc(1, sizeof(*status));
203 1 : if (!status) {
204 0 : SPDK_ERRLOG("Failed to allocate status tracker\n");
205 0 : spdk_free(nsdata_nvm);
206 0 : return -ENOMEM;
207 : }
208 :
209 1 : rc = nvme_ctrlr_cmd_identify(ctrlr, SPDK_NVME_IDENTIFY_NS_IOCS, 0, ns->id, ns->csi,
210 : nsdata_nvm, sizeof(*nsdata_nvm),
211 : nvme_completion_poll_cb, status);
212 1 : if (rc != 0) {
213 0 : spdk_free(nsdata_nvm);
214 0 : free(status);
215 0 : return rc;
216 : }
217 :
218 1 : if (nvme_wait_for_completion_robust_lock(ctrlr->adminq, status, &ctrlr->ctrlr_lock)) {
219 0 : SPDK_ERRLOG("Failed to retrieve Identify IOCS Specific Namespace Data Structure\n");
220 0 : spdk_free(nsdata_nvm);
221 0 : if (!status->timed_out) {
222 0 : free(status);
223 : }
224 0 : return -ENXIO;
225 : }
226 1 : free(status);
227 1 : ns->nsdata_nvm = nsdata_nvm;
228 :
229 1 : return 0;
230 : }
231 :
232 : static int
233 2 : nvme_ctrlr_identify_ns_iocs_specific(struct spdk_nvme_ns *ns)
234 : {
235 2 : switch (ns->csi) {
236 1 : case SPDK_NVME_CSI_ZNS:
237 1 : return nvme_ctrlr_identify_ns_zns_specific(ns);
238 1 : case SPDK_NVME_CSI_NVM:
239 1 : if (ns->ctrlr->cdata.ctratt.bits.elbas) {
240 1 : return nvme_ctrlr_identify_ns_nvm_specific(ns);
241 : }
242 : /* fallthrough */
243 : default:
244 : /*
245 : * This switch must handle all cases for which
246 : * nvme_ns_has_supported_iocs_specific_data() returns true,
247 : * other cases should never happen.
248 : */
249 0 : assert(0);
250 : }
251 :
252 : return -EINVAL;
253 : }
254 :
255 : static int
256 3 : nvme_ctrlr_identify_id_desc(struct spdk_nvme_ns *ns)
257 : {
258 : struct nvme_completion_poll_status *status;
259 : int rc;
260 :
261 3 : memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
262 :
263 3 : if ((ns->ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) &&
264 2 : !(ns->ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS)) ||
265 1 : (ns->ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
266 2 : SPDK_DEBUGLOG(nvme, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n");
267 2 : return 0;
268 : }
269 :
270 1 : status = calloc(1, sizeof(*status));
271 1 : if (!status) {
272 0 : SPDK_ERRLOG("Failed to allocate status tracker\n");
273 0 : return -ENOMEM;
274 : }
275 :
276 1 : SPDK_DEBUGLOG(nvme, "Attempting to retrieve NS ID Descriptor List\n");
277 1 : rc = nvme_ctrlr_cmd_identify(ns->ctrlr, SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST, 0, ns->id,
278 1 : 0, ns->id_desc_list, sizeof(ns->id_desc_list),
279 : nvme_completion_poll_cb, status);
280 1 : if (rc < 0) {
281 0 : free(status);
282 0 : return rc;
283 : }
284 :
285 1 : rc = nvme_wait_for_completion_robust_lock(ns->ctrlr->adminq, status, &ns->ctrlr->ctrlr_lock);
286 1 : if (rc != 0) {
287 0 : SPDK_WARNLOG("Failed to retrieve NS ID Descriptor List\n");
288 0 : memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
289 : }
290 :
291 1 : if (!status->timed_out) {
292 1 : free(status);
293 : }
294 :
295 1 : nvme_ns_set_id_desc_list_data(ns);
296 :
297 1 : return rc;
298 : }
299 :
300 : uint32_t
301 3 : spdk_nvme_ns_get_id(struct spdk_nvme_ns *ns)
302 : {
303 3 : return ns->id;
304 : }
305 :
306 : bool
307 16 : spdk_nvme_ns_is_active(struct spdk_nvme_ns *ns)
308 : {
309 16 : const struct spdk_nvme_ns_data *nsdata = NULL;
310 :
311 : /*
312 : * According to the spec, valid NS has non-zero id.
313 : */
314 16 : if (ns->id == 0) {
315 1 : return false;
316 : }
317 :
318 15 : nsdata = _nvme_ns_get_data(ns);
319 :
320 : /*
321 : * According to the spec, Identify Namespace will return a zero-filled structure for
322 : * inactive namespace IDs.
323 : * Check NCAP since it must be nonzero for an active namespace.
324 : */
325 15 : return nsdata->ncap != 0;
326 : }
327 :
328 : struct spdk_nvme_ctrlr *
329 1 : spdk_nvme_ns_get_ctrlr(struct spdk_nvme_ns *ns)
330 : {
331 1 : return ns->ctrlr;
332 : }
333 :
334 : uint32_t
335 28 : spdk_nvme_ns_get_max_io_xfer_size(struct spdk_nvme_ns *ns)
336 : {
337 28 : return ns->ctrlr->max_xfer_size;
338 : }
339 :
340 : uint32_t
341 3 : spdk_nvme_ns_get_sector_size(struct spdk_nvme_ns *ns)
342 : {
343 3 : return ns->sector_size;
344 : }
345 :
346 : uint32_t
347 2 : spdk_nvme_ns_get_extended_sector_size(struct spdk_nvme_ns *ns)
348 : {
349 2 : return ns->extended_lba_size;
350 : }
351 :
352 : uint64_t
353 4 : spdk_nvme_ns_get_num_sectors(struct spdk_nvme_ns *ns)
354 : {
355 4 : return _nvme_ns_get_data(ns)->nsze;
356 : }
357 :
358 : uint64_t
359 1 : spdk_nvme_ns_get_size(struct spdk_nvme_ns *ns)
360 : {
361 1 : return spdk_nvme_ns_get_num_sectors(ns) * spdk_nvme_ns_get_sector_size(ns);
362 : }
363 :
364 : uint32_t
365 9 : spdk_nvme_ns_get_flags(struct spdk_nvme_ns *ns)
366 : {
367 9 : return ns->flags;
368 : }
369 :
370 : enum spdk_nvme_pi_type
371 2 : spdk_nvme_ns_get_pi_type(struct spdk_nvme_ns *ns) {
372 2 : return ns->pi_type;
373 : }
374 :
375 : enum spdk_nvme_pi_format
376 1 : spdk_nvme_ns_get_pi_format(struct spdk_nvme_ns *ns) {
377 1 : return ns->pi_format;
378 : }
379 :
380 : bool
381 2 : spdk_nvme_ns_supports_extended_lba(struct spdk_nvme_ns *ns)
382 : {
383 2 : return (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) ? true : false;
384 : }
385 :
386 : bool
387 2 : spdk_nvme_ns_supports_compare(struct spdk_nvme_ns *ns)
388 : {
389 2 : return (ns->flags & SPDK_NVME_NS_COMPARE_SUPPORTED) ? true : false;
390 : }
391 :
392 : uint32_t
393 2 : spdk_nvme_ns_get_md_size(struct spdk_nvme_ns *ns)
394 : {
395 2 : return ns->md_size;
396 : }
397 :
398 : uint32_t
399 13 : spdk_nvme_ns_get_format_index(const struct spdk_nvme_ns_data *nsdata)
400 : {
401 13 : if (nsdata->nlbaf < 16) {
402 13 : return nsdata->flbas.format;
403 : } else {
404 0 : return ((nsdata->flbas.msb_format << 4) + nsdata->flbas.format);
405 : }
406 : }
407 :
408 : const struct spdk_nvme_ns_data *
409 5 : spdk_nvme_ns_get_data(struct spdk_nvme_ns *ns)
410 : {
411 5 : return _nvme_ns_get_data(ns);
412 : }
413 :
414 : const struct spdk_nvme_nvm_ns_data *
415 0 : spdk_nvme_nvm_ns_get_data(struct spdk_nvme_ns *ns)
416 : {
417 0 : return ns->nsdata_nvm;
418 : }
419 :
420 : /* We have to use the typedef in the function declaration to appease astyle. */
421 : typedef enum spdk_nvme_dealloc_logical_block_read_value
422 : spdk_nvme_dealloc_logical_block_read_value_t;
423 :
424 : spdk_nvme_dealloc_logical_block_read_value_t
425 2 : spdk_nvme_ns_get_dealloc_logical_block_read_value(
426 : struct spdk_nvme_ns *ns)
427 : {
428 2 : struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr;
429 2 : const struct spdk_nvme_ns_data *data = spdk_nvme_ns_get_data(ns);
430 :
431 2 : if (ctrlr->quirks & NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE) {
432 1 : return SPDK_NVME_DEALLOC_READ_00;
433 : } else {
434 1 : return data->dlfeat.bits.read_value;
435 : }
436 : }
437 :
438 : uint32_t
439 2 : spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns)
440 : {
441 2 : return ns->sectors_per_stripe;
442 : }
443 :
444 : static const void *
445 13 : nvme_ns_find_id_desc(const struct spdk_nvme_ns *ns, enum spdk_nvme_nidt type, size_t *length)
446 : {
447 : const struct spdk_nvme_ns_id_desc *desc;
448 : size_t offset;
449 :
450 13 : offset = 0;
451 17 : while (offset + 4 < sizeof(ns->id_desc_list)) {
452 17 : desc = (const struct spdk_nvme_ns_id_desc *)&ns->id_desc_list[offset];
453 :
454 17 : if (desc->nidl == 0) {
455 : /* End of list */
456 6 : return NULL;
457 : }
458 :
459 : /*
460 : * Check if this descriptor fits within the list.
461 : * 4 is the fixed-size descriptor header (not counted in NIDL).
462 : */
463 11 : if (offset + desc->nidl + 4 > sizeof(ns->id_desc_list)) {
464 : /* Descriptor longer than remaining space in list (invalid) */
465 0 : return NULL;
466 : }
467 :
468 11 : if (desc->nidt == type) {
469 7 : *length = desc->nidl;
470 7 : return &desc->nid[0];
471 : }
472 :
473 4 : offset += 4 + desc->nidl;
474 : }
475 :
476 0 : return NULL;
477 : }
478 :
479 : const uint8_t *
480 0 : spdk_nvme_ns_get_nguid(const struct spdk_nvme_ns *ns)
481 : {
482 : const uint8_t *nguid;
483 0 : size_t size;
484 :
485 0 : nguid = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_NGUID, &size);
486 0 : if (nguid && size != SPDK_SIZEOF_MEMBER(struct spdk_nvme_ns_data, nguid)) {
487 0 : SPDK_WARNLOG("Invalid NIDT_NGUID descriptor length reported: %zu (expected: %zu)\n",
488 : size, SPDK_SIZEOF_MEMBER(struct spdk_nvme_ns_data, nguid));
489 0 : return NULL;
490 : }
491 :
492 0 : return nguid;
493 : }
494 :
495 : const struct spdk_uuid *
496 5 : spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns)
497 : {
498 : const struct spdk_uuid *uuid;
499 5 : size_t uuid_size;
500 :
501 5 : uuid = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_UUID, &uuid_size);
502 5 : if (uuid && uuid_size != sizeof(*uuid)) {
503 0 : SPDK_WARNLOG("Invalid NIDT_UUID descriptor length reported: %zu (expected: %zu)\n",
504 : uuid_size, sizeof(*uuid));
505 0 : return NULL;
506 : }
507 :
508 5 : return uuid;
509 : }
510 :
511 : static enum spdk_nvme_csi
512 5 : nvme_ns_get_csi(const struct spdk_nvme_ns *ns) {
513 : const uint8_t *csi;
514 5 : size_t csi_size;
515 :
516 5 : csi = nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_CSI, &csi_size);
517 5 : if (csi && csi_size != sizeof(*csi))
518 : {
519 0 : SPDK_WARNLOG("Invalid NIDT_CSI descriptor length reported: %zu (expected: %zu)\n",
520 : csi_size, sizeof(*csi));
521 0 : return SPDK_NVME_CSI_NVM;
522 : }
523 5 : if (!csi)
524 : {
525 2 : if (ns->ctrlr->cap.bits.css & SPDK_NVME_CAP_CSS_IOCS) {
526 1 : SPDK_WARNLOG("CSI not reported for NSID: %" PRIu32 "\n", ns->id);
527 : }
528 2 : return SPDK_NVME_CSI_NVM;
529 : }
530 :
531 3 : return *csi;
532 : }
533 :
534 : void
535 1 : nvme_ns_set_id_desc_list_data(struct spdk_nvme_ns *ns)
536 : {
537 1 : ns->csi = nvme_ns_get_csi(ns);
538 1 : }
539 :
540 : enum spdk_nvme_csi
541 2 : spdk_nvme_ns_get_csi(const struct spdk_nvme_ns *ns) {
542 2 : return ns->csi;
543 : }
544 :
545 : void
546 13 : nvme_ns_free_zns_specific_data(struct spdk_nvme_ns *ns)
547 : {
548 13 : if (!ns->id) {
549 0 : return;
550 : }
551 :
552 13 : if (ns->nsdata_zns) {
553 1 : spdk_free(ns->nsdata_zns);
554 1 : ns->nsdata_zns = NULL;
555 : }
556 : }
557 :
558 : void
559 11 : nvme_ns_free_nvm_specific_data(struct spdk_nvme_ns *ns)
560 : {
561 11 : if (!ns->id) {
562 0 : return;
563 : }
564 :
565 11 : if (ns->nsdata_nvm) {
566 1 : spdk_free(ns->nsdata_nvm);
567 1 : ns->nsdata_nvm = NULL;
568 : }
569 : }
570 :
571 : void
572 10 : nvme_ns_free_iocs_specific_data(struct spdk_nvme_ns *ns)
573 : {
574 10 : nvme_ns_free_zns_specific_data(ns);
575 10 : nvme_ns_free_nvm_specific_data(ns);
576 10 : }
577 :
578 : bool
579 5 : nvme_ns_has_supported_iocs_specific_data(struct spdk_nvme_ns *ns)
580 : {
581 5 : switch (ns->csi) {
582 3 : case SPDK_NVME_CSI_NVM:
583 3 : if (ns->ctrlr->cdata.ctratt.bits.elbas) {
584 1 : return true;
585 : }
586 :
587 2 : return false;
588 1 : case SPDK_NVME_CSI_ZNS:
589 1 : return true;
590 1 : default:
591 1 : SPDK_WARNLOG("Unsupported CSI: %u for NSID: %u\n", ns->csi, ns->id);
592 1 : return false;
593 : }
594 : }
595 :
596 : uint32_t
597 1 : spdk_nvme_ns_get_ana_group_id(const struct spdk_nvme_ns *ns)
598 : {
599 1 : return ns->ana_group_id;
600 : }
601 :
602 : enum spdk_nvme_ana_state
603 1 : spdk_nvme_ns_get_ana_state(const struct spdk_nvme_ns *ns) {
604 1 : return ns->ana_state;
605 : }
606 :
607 : int
608 11 : nvme_ns_construct(struct spdk_nvme_ns *ns, uint32_t id,
609 : struct spdk_nvme_ctrlr *ctrlr)
610 : {
611 : int rc;
612 :
613 11 : assert(id > 0);
614 :
615 11 : ns->ctrlr = ctrlr;
616 11 : ns->id = id;
617 : /* This will be overwritten when reading ANA log page. */
618 11 : ns->ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
619 :
620 11 : rc = nvme_ctrlr_identify_ns(ns);
621 11 : if (rc != 0) {
622 0 : return rc;
623 : }
624 :
625 : /* skip Identify NS ID Descriptor List for inactive NS */
626 11 : if (!spdk_nvme_ns_is_active(ns)) {
627 10 : return 0;
628 : }
629 :
630 1 : rc = nvme_ctrlr_identify_id_desc(ns);
631 1 : if (rc != 0) {
632 0 : return rc;
633 : }
634 :
635 2 : if (nvme_ctrlr_multi_iocs_enabled(ctrlr) &&
636 1 : nvme_ns_has_supported_iocs_specific_data(ns)) {
637 0 : rc = nvme_ctrlr_identify_ns_iocs_specific(ns);
638 0 : if (rc != 0) {
639 0 : return rc;
640 : }
641 : }
642 :
643 1 : return 0;
644 : }
645 :
646 : void
647 10 : nvme_ns_destruct(struct spdk_nvme_ns *ns)
648 : {
649 : struct spdk_nvme_ns_data *nsdata;
650 :
651 10 : if (!ns->id) {
652 0 : return;
653 : }
654 :
655 10 : nsdata = _nvme_ns_get_data(ns);
656 10 : memset(nsdata, 0, sizeof(*nsdata));
657 10 : memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list));
658 10 : nvme_ns_free_iocs_specific_data(ns);
659 10 : ns->sector_size = 0;
660 10 : ns->extended_lba_size = 0;
661 10 : ns->md_size = 0;
662 10 : ns->pi_type = 0;
663 10 : ns->sectors_per_max_io = 0;
664 10 : ns->sectors_per_max_io_no_md = 0;
665 10 : ns->sectors_per_stripe = 0;
666 10 : ns->flags = 0;
667 10 : ns->csi = SPDK_NVME_CSI_NVM;
668 : }
|