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