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