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(SPDK_LOG_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(SPDK_LOG_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, 128 nsdata, sizeof(*nsdata), 129 nvme_completion_poll_cb, status); 130 if (rc != 0) { 131 free(status); 132 return rc; 133 } 134 135 if (spdk_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_id_desc(struct spdk_nvme_ns *ns) 154 { 155 struct nvme_completion_poll_status *status; 156 int rc; 157 158 memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list)); 159 160 if (ns->ctrlr->vs.raw < SPDK_NVME_VERSION(1, 3, 0) || 161 (ns->ctrlr->quirks & NVME_QUIRK_IDENTIFY_CNS)) { 162 SPDK_DEBUGLOG(SPDK_LOG_NVME, "Version < 1.3; not attempting to retrieve NS ID Descriptor List\n"); 163 return 0; 164 } 165 166 status = calloc(1, sizeof(*status)); 167 if (!status) { 168 SPDK_ERRLOG("Failed to allocate status tracker\n"); 169 return -ENOMEM; 170 } 171 172 SPDK_DEBUGLOG(SPDK_LOG_NVME, "Attempting to retrieve NS ID Descriptor List\n"); 173 rc = nvme_ctrlr_cmd_identify(ns->ctrlr, SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST, 0, ns->id, 174 ns->id_desc_list, sizeof(ns->id_desc_list), 175 nvme_completion_poll_cb, status); 176 if (rc < 0) { 177 free(status); 178 return rc; 179 } 180 181 rc = spdk_nvme_wait_for_completion_robust_lock(ns->ctrlr->adminq, status, &ns->ctrlr->ctrlr_lock); 182 if (rc != 0) { 183 SPDK_WARNLOG("Failed to retrieve NS ID Descriptor List\n"); 184 memset(ns->id_desc_list, 0, sizeof(ns->id_desc_list)); 185 } 186 187 if (!status->timed_out) { 188 free(status); 189 } 190 191 return rc; 192 } 193 194 uint32_t 195 spdk_nvme_ns_get_id(struct spdk_nvme_ns *ns) 196 { 197 return ns->id; 198 } 199 200 bool 201 spdk_nvme_ns_is_active(struct spdk_nvme_ns *ns) 202 { 203 const struct spdk_nvme_ns_data *nsdata = NULL; 204 205 /* 206 * According to the spec, valid NS has non-zero id. 207 */ 208 if (ns->id == 0) { 209 return false; 210 } 211 212 nsdata = _nvme_ns_get_data(ns); 213 214 /* 215 * According to the spec, Identify Namespace will return a zero-filled structure for 216 * inactive namespace IDs. 217 * Check NCAP since it must be nonzero for an active namespace. 218 */ 219 return nsdata->ncap != 0; 220 } 221 222 struct spdk_nvme_ctrlr * 223 spdk_nvme_ns_get_ctrlr(struct spdk_nvme_ns *ns) 224 { 225 return ns->ctrlr; 226 } 227 228 uint32_t 229 spdk_nvme_ns_get_max_io_xfer_size(struct spdk_nvme_ns *ns) 230 { 231 return ns->ctrlr->max_xfer_size; 232 } 233 234 uint32_t 235 spdk_nvme_ns_get_sector_size(struct spdk_nvme_ns *ns) 236 { 237 return ns->sector_size; 238 } 239 240 uint32_t 241 spdk_nvme_ns_get_extended_sector_size(struct spdk_nvme_ns *ns) 242 { 243 return ns->extended_lba_size; 244 } 245 246 uint64_t 247 spdk_nvme_ns_get_num_sectors(struct spdk_nvme_ns *ns) 248 { 249 return _nvme_ns_get_data(ns)->nsze; 250 } 251 252 uint64_t 253 spdk_nvme_ns_get_size(struct spdk_nvme_ns *ns) 254 { 255 return spdk_nvme_ns_get_num_sectors(ns) * spdk_nvme_ns_get_sector_size(ns); 256 } 257 258 uint32_t 259 spdk_nvme_ns_get_flags(struct spdk_nvme_ns *ns) 260 { 261 return ns->flags; 262 } 263 264 enum spdk_nvme_pi_type 265 spdk_nvme_ns_get_pi_type(struct spdk_nvme_ns *ns) { 266 return ns->pi_type; 267 } 268 269 bool 270 spdk_nvme_ns_supports_extended_lba(struct spdk_nvme_ns *ns) 271 { 272 return (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) ? true : false; 273 } 274 275 bool 276 spdk_nvme_ns_supports_compare(struct spdk_nvme_ns *ns) 277 { 278 return (ns->flags & SPDK_NVME_NS_COMPARE_SUPPORTED) ? true : false; 279 } 280 281 uint32_t 282 spdk_nvme_ns_get_md_size(struct spdk_nvme_ns *ns) 283 { 284 return ns->md_size; 285 } 286 287 const struct spdk_nvme_ns_data * 288 spdk_nvme_ns_get_data(struct spdk_nvme_ns *ns) 289 { 290 return _nvme_ns_get_data(ns); 291 } 292 293 enum spdk_nvme_dealloc_logical_block_read_value spdk_nvme_ns_get_dealloc_logical_block_read_value( 294 struct spdk_nvme_ns *ns) 295 { 296 struct spdk_nvme_ctrlr *ctrlr = ns->ctrlr; 297 const struct spdk_nvme_ns_data *data = spdk_nvme_ns_get_data(ns); 298 299 if (ctrlr->quirks & NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE) { 300 return SPDK_NVME_DEALLOC_READ_00; 301 } else { 302 return data->dlfeat.bits.read_value; 303 } 304 } 305 306 uint32_t 307 spdk_nvme_ns_get_optimal_io_boundary(struct spdk_nvme_ns *ns) 308 { 309 return ns->sectors_per_stripe; 310 } 311 312 static const void * 313 _spdk_nvme_ns_find_id_desc(const struct spdk_nvme_ns *ns, enum spdk_nvme_nidt type, size_t *length) 314 { 315 const struct spdk_nvme_ns_id_desc *desc; 316 size_t offset; 317 318 offset = 0; 319 while (offset + 4 < sizeof(ns->id_desc_list)) { 320 desc = (const struct spdk_nvme_ns_id_desc *)&ns->id_desc_list[offset]; 321 322 if (desc->nidl == 0) { 323 /* End of list */ 324 return NULL; 325 } 326 327 /* 328 * Check if this descriptor fits within the list. 329 * 4 is the fixed-size descriptor header (not counted in NIDL). 330 */ 331 if (offset + desc->nidl + 4 > sizeof(ns->id_desc_list)) { 332 /* Descriptor longer than remaining space in list (invalid) */ 333 return NULL; 334 } 335 336 if (desc->nidt == type) { 337 *length = desc->nidl; 338 return &desc->nid[0]; 339 } 340 341 offset += 4 + desc->nidl; 342 } 343 344 return NULL; 345 } 346 347 const struct spdk_uuid * 348 spdk_nvme_ns_get_uuid(const struct spdk_nvme_ns *ns) 349 { 350 const struct spdk_uuid *uuid; 351 size_t uuid_size; 352 353 uuid = _spdk_nvme_ns_find_id_desc(ns, SPDK_NVME_NIDT_UUID, &uuid_size); 354 if (uuid == NULL || uuid_size != sizeof(*uuid)) { 355 return NULL; 356 } 357 358 return uuid; 359 } 360 361 int nvme_ns_construct(struct spdk_nvme_ns *ns, uint32_t id, 362 struct spdk_nvme_ctrlr *ctrlr) 363 { 364 int rc; 365 366 assert(id > 0); 367 368 ns->ctrlr = ctrlr; 369 ns->id = id; 370 371 rc = nvme_ctrlr_identify_ns(ns); 372 if (rc != 0) { 373 return rc; 374 } 375 376 return nvme_ctrlr_identify_id_desc(ns); 377 } 378 379 void nvme_ns_destruct(struct spdk_nvme_ns *ns) 380 { 381 struct spdk_nvme_ns_data *nsdata; 382 383 if (!ns->id) { 384 return; 385 } 386 387 nsdata = _nvme_ns_get_data(ns); 388 memset(nsdata, 0, sizeof(*nsdata)); 389 ns->sector_size = 0; 390 ns->extended_lba_size = 0; 391 ns->md_size = 0; 392 ns->pi_type = 0; 393 ns->sectors_per_max_io = 0; 394 ns->sectors_per_stripe = 0; 395 ns->flags = 0; 396 } 397 398 int nvme_ns_update(struct spdk_nvme_ns *ns) 399 { 400 return nvme_ctrlr_identify_ns(ns); 401 } 402