1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * 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 struct nvme_request *_nvme_ns_cmd_rw(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 37 const struct nvme_payload *payload, uint32_t payload_offset, uint32_t md_offset, 38 uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, 39 void *cb_arg, uint32_t opc, uint32_t io_flags, 40 uint16_t apptag_mask, uint16_t apptag, bool check_sgl); 41 42 43 static bool 44 spdk_nvme_ns_check_request_length(uint32_t lba_count, uint32_t sectors_per_max_io, 45 uint32_t sectors_per_stripe, uint32_t qdepth) 46 { 47 uint32_t child_per_io; 48 49 if (sectors_per_stripe > 0) { 50 child_per_io = (lba_count + sectors_per_stripe - 1) / sectors_per_stripe; 51 } else { 52 child_per_io = (lba_count + sectors_per_max_io - 1) / sectors_per_max_io; 53 } 54 55 SPDK_DEBUGLOG(SPDK_LOG_NVME, "checking maximum i/o length %d\n", child_per_io); 56 57 return child_per_io >= qdepth; 58 } 59 60 static void 61 nvme_cb_complete_child(void *child_arg, const struct spdk_nvme_cpl *cpl) 62 { 63 struct nvme_request *child = child_arg; 64 struct nvme_request *parent = child->parent; 65 66 nvme_request_remove_child(parent, child); 67 68 if (spdk_nvme_cpl_is_error(cpl)) { 69 memcpy(&parent->parent_status, cpl, sizeof(*cpl)); 70 } 71 72 if (parent->num_children == 0) { 73 nvme_complete_request(parent->cb_fn, parent->cb_arg, parent, &parent->parent_status); 74 nvme_free_request(parent); 75 } 76 } 77 78 static void 79 nvme_request_add_child(struct nvme_request *parent, struct nvme_request *child) 80 { 81 assert(parent->num_children != UINT16_MAX); 82 83 if (parent->num_children == 0) { 84 /* 85 * Defer initialization of the children TAILQ since it falls 86 * on a separate cacheline. This ensures we do not touch this 87 * cacheline except on request splitting cases, which are 88 * relatively rare. 89 */ 90 TAILQ_INIT(&parent->children); 91 parent->parent = NULL; 92 memset(&parent->parent_status, 0, sizeof(struct spdk_nvme_cpl)); 93 } 94 95 parent->num_children++; 96 TAILQ_INSERT_TAIL(&parent->children, child, child_tailq); 97 child->parent = parent; 98 child->cb_fn = nvme_cb_complete_child; 99 child->cb_arg = child; 100 } 101 102 void 103 nvme_request_remove_child(struct nvme_request *parent, struct nvme_request *child) 104 { 105 assert(parent != NULL); 106 assert(child != NULL); 107 assert(child->parent == parent); 108 assert(parent->num_children != 0); 109 110 parent->num_children--; 111 TAILQ_REMOVE(&parent->children, child, child_tailq); 112 } 113 114 static void 115 nvme_request_free_children(struct nvme_request *req) 116 { 117 struct nvme_request *child, *tmp; 118 119 if (req->num_children == 0) { 120 return; 121 } 122 123 /* free all child nvme_request */ 124 TAILQ_FOREACH_SAFE(child, &req->children, child_tailq, tmp) { 125 nvme_request_remove_child(req, child); 126 nvme_request_free_children(child); 127 nvme_free_request(child); 128 } 129 } 130 131 static struct nvme_request * 132 _nvme_add_child_request(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 133 const struct nvme_payload *payload, 134 uint32_t payload_offset, uint32_t md_offset, 135 uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc, 136 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag, 137 struct nvme_request *parent, bool check_sgl) 138 { 139 struct nvme_request *child; 140 141 child = _nvme_ns_cmd_rw(ns, qpair, payload, payload_offset, md_offset, lba, lba_count, cb_fn, 142 cb_arg, opc, io_flags, apptag_mask, apptag, check_sgl); 143 if (child == NULL) { 144 nvme_request_free_children(parent); 145 nvme_free_request(parent); 146 return NULL; 147 } 148 149 nvme_request_add_child(parent, child); 150 return child; 151 } 152 153 static struct nvme_request * 154 _nvme_ns_cmd_split_request(struct spdk_nvme_ns *ns, 155 struct spdk_nvme_qpair *qpair, 156 const struct nvme_payload *payload, 157 uint32_t payload_offset, uint32_t md_offset, 158 uint64_t lba, uint32_t lba_count, 159 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc, 160 uint32_t io_flags, struct nvme_request *req, 161 uint32_t sectors_per_max_io, uint32_t sector_mask, 162 uint16_t apptag_mask, uint16_t apptag) 163 { 164 uint32_t sector_size; 165 uint32_t md_size = ns->md_size; 166 uint32_t remaining_lba_count = lba_count; 167 struct nvme_request *child; 168 169 sector_size = ns->extended_lba_size; 170 171 if ((io_flags & SPDK_NVME_IO_FLAGS_PRACT) && 172 (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) && 173 (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) && 174 (md_size == 8)) { 175 sector_size -= 8; 176 } 177 178 while (remaining_lba_count > 0) { 179 lba_count = sectors_per_max_io - (lba & sector_mask); 180 lba_count = spdk_min(remaining_lba_count, lba_count); 181 182 child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset, 183 lba, lba_count, cb_fn, cb_arg, opc, 184 io_flags, apptag_mask, apptag, req, true); 185 if (child == NULL) { 186 return NULL; 187 } 188 189 remaining_lba_count -= lba_count; 190 lba += lba_count; 191 payload_offset += lba_count * sector_size; 192 md_offset += lba_count * md_size; 193 } 194 195 return req; 196 } 197 198 static void 199 _nvme_ns_cmd_setup_request(struct spdk_nvme_ns *ns, struct nvme_request *req, 200 uint32_t opc, uint64_t lba, uint32_t lba_count, 201 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag) 202 { 203 struct spdk_nvme_cmd *cmd; 204 205 cmd = &req->cmd; 206 cmd->opc = opc; 207 cmd->nsid = ns->id; 208 209 *(uint64_t *)&cmd->cdw10 = lba; 210 211 if (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) { 212 switch (ns->pi_type) { 213 case SPDK_NVME_FMT_NVM_PROTECTION_TYPE1: 214 case SPDK_NVME_FMT_NVM_PROTECTION_TYPE2: 215 cmd->cdw14 = (uint32_t)lba; 216 break; 217 } 218 } 219 220 cmd->cdw12 = lba_count - 1; 221 cmd->cdw12 |= io_flags; 222 223 cmd->cdw15 = apptag_mask; 224 cmd->cdw15 = (cmd->cdw15 << 16 | apptag); 225 } 226 227 static struct nvme_request * 228 _nvme_ns_cmd_split_request_prp(struct spdk_nvme_ns *ns, 229 struct spdk_nvme_qpair *qpair, 230 const struct nvme_payload *payload, 231 uint32_t payload_offset, uint32_t md_offset, 232 uint64_t lba, uint32_t lba_count, 233 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc, 234 uint32_t io_flags, struct nvme_request *req, 235 uint16_t apptag_mask, uint16_t apptag) 236 { 237 spdk_nvme_req_reset_sgl_cb reset_sgl_fn = req->payload.reset_sgl_fn; 238 spdk_nvme_req_next_sge_cb next_sge_fn = req->payload.next_sge_fn; 239 void *sgl_cb_arg = req->payload.contig_or_cb_arg; 240 bool start_valid, end_valid, last_sge, child_equals_parent; 241 uint64_t child_lba = lba; 242 uint32_t req_current_length = 0; 243 uint32_t child_length = 0; 244 uint32_t sge_length; 245 uint32_t page_size = qpair->ctrlr->page_size; 246 uintptr_t address; 247 248 reset_sgl_fn(sgl_cb_arg, payload_offset); 249 next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length); 250 while (req_current_length < req->payload_size) { 251 252 if (sge_length == 0) { 253 continue; 254 } else if (req_current_length + sge_length > req->payload_size) { 255 sge_length = req->payload_size - req_current_length; 256 } 257 258 /* 259 * The start of the SGE is invalid if the start address is not page aligned, 260 * unless it is the first SGE in the child request. 261 */ 262 start_valid = child_length == 0 || _is_page_aligned(address, page_size); 263 264 /* Boolean for whether this is the last SGE in the parent request. */ 265 last_sge = (req_current_length + sge_length == req->payload_size); 266 267 /* 268 * The end of the SGE is invalid if the end address is not page aligned, 269 * unless it is the last SGE in the parent request. 270 */ 271 end_valid = last_sge || _is_page_aligned(address + sge_length, page_size); 272 273 /* 274 * This child request equals the parent request, meaning that no splitting 275 * was required for the parent request (the one passed into this function). 276 * In this case, we do not create a child request at all - we just send 277 * the original request as a single request at the end of this function. 278 */ 279 child_equals_parent = (child_length + sge_length == req->payload_size); 280 281 if (start_valid) { 282 /* 283 * The start of the SGE is valid, so advance the length parameters, 284 * to include this SGE with previous SGEs for this child request 285 * (if any). If it is not valid, we do not advance the length 286 * parameters nor get the next SGE, because we must send what has 287 * been collected before this SGE as a child request. 288 */ 289 child_length += sge_length; 290 req_current_length += sge_length; 291 if (req_current_length < req->payload_size) { 292 next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length); 293 } 294 /* 295 * If the next SGE is not page aligned, we will need to create a child 296 * request for what we have so far, and then start a new child request for 297 * the next SGE. 298 */ 299 start_valid = _is_page_aligned(address, page_size); 300 } 301 302 if (start_valid && end_valid && !last_sge) { 303 continue; 304 } 305 306 /* 307 * We need to create a split here. Send what we have accumulated so far as a child 308 * request. Checking if child_equals_parent allows us to *not* create a child request 309 * when no splitting is required - in that case we will fall-through and just create 310 * a single request with no children for the entire I/O. 311 */ 312 if (!child_equals_parent) { 313 struct nvme_request *child; 314 uint32_t child_lba_count; 315 316 if ((child_length % ns->extended_lba_size) != 0) { 317 SPDK_ERRLOG("child_length %u not even multiple of lba_size %u\n", 318 child_length, ns->extended_lba_size); 319 return NULL; 320 } 321 child_lba_count = child_length / ns->extended_lba_size; 322 /* 323 * Note the last parameter is set to "false" - this tells the recursive 324 * call to _nvme_ns_cmd_rw() to not bother with checking for SGL splitting 325 * since we have already verified it here. 326 */ 327 child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset, 328 child_lba, child_lba_count, 329 cb_fn, cb_arg, opc, io_flags, 330 apptag_mask, apptag, req, false); 331 if (child == NULL) { 332 return NULL; 333 } 334 payload_offset += child_length; 335 md_offset += child_lba_count * ns->md_size; 336 child_lba += child_lba_count; 337 child_length = 0; 338 } 339 } 340 341 if (child_length == req->payload_size) { 342 /* No splitting was required, so setup the whole payload as one request. */ 343 _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag); 344 } 345 346 return req; 347 } 348 349 static struct nvme_request * 350 _nvme_ns_cmd_split_request_sgl(struct spdk_nvme_ns *ns, 351 struct spdk_nvme_qpair *qpair, 352 const struct nvme_payload *payload, 353 uint32_t payload_offset, uint32_t md_offset, 354 uint64_t lba, uint32_t lba_count, 355 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc, 356 uint32_t io_flags, struct nvme_request *req, 357 uint16_t apptag_mask, uint16_t apptag) 358 { 359 spdk_nvme_req_reset_sgl_cb reset_sgl_fn = req->payload.reset_sgl_fn; 360 spdk_nvme_req_next_sge_cb next_sge_fn = req->payload.next_sge_fn; 361 void *sgl_cb_arg = req->payload.contig_or_cb_arg; 362 uint64_t child_lba = lba; 363 uint32_t req_current_length = 0; 364 uint32_t child_length = 0; 365 uint32_t sge_length; 366 uint16_t max_sges, num_sges; 367 uintptr_t address; 368 369 max_sges = ns->ctrlr->max_sges; 370 371 reset_sgl_fn(sgl_cb_arg, payload_offset); 372 num_sges = 0; 373 374 while (req_current_length < req->payload_size) { 375 next_sge_fn(sgl_cb_arg, (void **)&address, &sge_length); 376 377 if (req_current_length + sge_length > req->payload_size) { 378 sge_length = req->payload_size - req_current_length; 379 } 380 381 child_length += sge_length; 382 req_current_length += sge_length; 383 num_sges++; 384 385 if (num_sges < max_sges && req_current_length < req->payload_size) { 386 continue; 387 } 388 389 /* 390 * We need to create a split here. Send what we have accumulated so far as a child 391 * request. Checking if the child equals the full payload allows us to *not* 392 * create a child request when no splitting is required - in that case we will 393 * fall-through and just create a single request with no children for the entire I/O. 394 */ 395 if (child_length != req->payload_size) { 396 struct nvme_request *child; 397 uint32_t child_lba_count; 398 399 if ((child_length % ns->extended_lba_size) != 0) { 400 SPDK_ERRLOG("child_length %u not even multiple of lba_size %u\n", 401 child_length, ns->extended_lba_size); 402 return NULL; 403 } 404 child_lba_count = child_length / ns->extended_lba_size; 405 /* 406 * Note the last parameter is set to "false" - this tells the recursive 407 * call to _nvme_ns_cmd_rw() to not bother with checking for SGL splitting 408 * since we have already verified it here. 409 */ 410 child = _nvme_add_child_request(ns, qpair, payload, payload_offset, md_offset, 411 child_lba, child_lba_count, 412 cb_fn, cb_arg, opc, io_flags, 413 apptag_mask, apptag, req, false); 414 if (child == NULL) { 415 return NULL; 416 } 417 payload_offset += child_length; 418 md_offset += child_lba_count * ns->md_size; 419 child_lba += child_lba_count; 420 child_length = 0; 421 num_sges = 0; 422 } 423 } 424 425 if (child_length == req->payload_size) { 426 /* No splitting was required, so setup the whole payload as one request. */ 427 _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag); 428 } 429 430 return req; 431 } 432 433 static struct nvme_request * 434 _nvme_ns_cmd_rw(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 435 const struct nvme_payload *payload, uint32_t payload_offset, uint32_t md_offset, 436 uint64_t lba, uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t opc, 437 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag, bool check_sgl) 438 { 439 struct nvme_request *req; 440 uint32_t sector_size; 441 uint32_t sectors_per_max_io; 442 uint32_t sectors_per_stripe; 443 444 if (io_flags & 0xFFFF) { 445 /* The bottom 16 bits must be empty */ 446 SPDK_ERRLOG("io_flags 0x%x bottom 16 bits is not empty\n", 447 io_flags); 448 return NULL; 449 } 450 451 sector_size = ns->extended_lba_size; 452 sectors_per_max_io = ns->sectors_per_max_io; 453 sectors_per_stripe = ns->sectors_per_stripe; 454 455 if ((io_flags & SPDK_NVME_IO_FLAGS_PRACT) && 456 (ns->flags & SPDK_NVME_NS_EXTENDED_LBA_SUPPORTED) && 457 (ns->flags & SPDK_NVME_NS_DPS_PI_SUPPORTED) && 458 (ns->md_size == 8)) { 459 sector_size -= 8; 460 } 461 462 req = nvme_allocate_request(qpair, payload, lba_count * sector_size, cb_fn, cb_arg); 463 if (req == NULL) { 464 return NULL; 465 } 466 467 req->payload_offset = payload_offset; 468 req->md_offset = md_offset; 469 470 /* 471 * Intel DC P3*00 NVMe controllers benefit from driver-assisted striping. 472 * If this controller defines a stripe boundary and this I/O spans a stripe 473 * boundary, split the request into multiple requests and submit each 474 * separately to hardware. 475 */ 476 if (sectors_per_stripe > 0 && 477 (((lba & (sectors_per_stripe - 1)) + lba_count) > sectors_per_stripe)) { 478 479 return _nvme_ns_cmd_split_request(ns, qpair, payload, payload_offset, md_offset, lba, lba_count, 480 cb_fn, 481 cb_arg, opc, 482 io_flags, req, sectors_per_stripe, sectors_per_stripe - 1, apptag_mask, apptag); 483 } else if (lba_count > sectors_per_max_io) { 484 return _nvme_ns_cmd_split_request(ns, qpair, payload, payload_offset, md_offset, lba, lba_count, 485 cb_fn, 486 cb_arg, opc, 487 io_flags, req, sectors_per_max_io, 0, apptag_mask, apptag); 488 } else if (nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_SGL && check_sgl) { 489 if (ns->ctrlr->flags & SPDK_NVME_CTRLR_SGL_SUPPORTED) { 490 return _nvme_ns_cmd_split_request_sgl(ns, qpair, payload, payload_offset, md_offset, 491 lba, lba_count, cb_fn, cb_arg, opc, io_flags, 492 req, apptag_mask, apptag); 493 } else { 494 return _nvme_ns_cmd_split_request_prp(ns, qpair, payload, payload_offset, md_offset, 495 lba, lba_count, cb_fn, cb_arg, opc, io_flags, 496 req, apptag_mask, apptag); 497 } 498 } 499 500 _nvme_ns_cmd_setup_request(ns, req, opc, lba, lba_count, io_flags, apptag_mask, apptag); 501 return req; 502 } 503 504 int 505 spdk_nvme_ns_cmd_compare(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer, 506 uint64_t lba, 507 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, 508 uint32_t io_flags) 509 { 510 struct nvme_request *req; 511 struct nvme_payload payload; 512 513 payload = NVME_PAYLOAD_CONTIG(buffer, NULL); 514 515 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, 516 SPDK_NVME_OPC_COMPARE, 517 io_flags, 0, 518 0, true); 519 if (req != NULL) { 520 return nvme_qpair_submit_request(qpair, req); 521 } else if (spdk_nvme_ns_check_request_length(lba_count, 522 ns->sectors_per_max_io, 523 ns->sectors_per_stripe, 524 qpair->ctrlr->opts.io_queue_requests)) { 525 return -EINVAL; 526 } else { 527 return -ENOMEM; 528 } 529 } 530 531 int 532 spdk_nvme_ns_cmd_compare_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 533 void *buffer, 534 void *metadata, 535 uint64_t lba, 536 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, 537 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag) 538 { 539 struct nvme_request *req; 540 struct nvme_payload payload; 541 542 payload = NVME_PAYLOAD_CONTIG(buffer, metadata); 543 544 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, 545 SPDK_NVME_OPC_COMPARE, 546 io_flags, 547 apptag_mask, apptag, true); 548 if (req != NULL) { 549 return nvme_qpair_submit_request(qpair, req); 550 } else if (spdk_nvme_ns_check_request_length(lba_count, 551 ns->sectors_per_max_io, 552 ns->sectors_per_stripe, 553 qpair->ctrlr->opts.io_queue_requests)) { 554 return -EINVAL; 555 } else { 556 return -ENOMEM; 557 } 558 } 559 560 int 561 spdk_nvme_ns_cmd_comparev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 562 uint64_t lba, uint32_t lba_count, 563 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags, 564 spdk_nvme_req_reset_sgl_cb reset_sgl_fn, 565 spdk_nvme_req_next_sge_cb next_sge_fn) 566 { 567 struct nvme_request *req; 568 struct nvme_payload payload; 569 570 if (reset_sgl_fn == NULL || next_sge_fn == NULL) { 571 return -EINVAL; 572 } 573 574 payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL); 575 576 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, 577 SPDK_NVME_OPC_COMPARE, 578 io_flags, 0, 0, true); 579 if (req != NULL) { 580 return nvme_qpair_submit_request(qpair, req); 581 } else if (spdk_nvme_ns_check_request_length(lba_count, 582 ns->sectors_per_max_io, 583 ns->sectors_per_stripe, 584 qpair->ctrlr->opts.io_queue_requests)) { 585 return -EINVAL; 586 } else { 587 return -ENOMEM; 588 } 589 } 590 591 int 592 spdk_nvme_ns_cmd_read(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer, 593 uint64_t lba, 594 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, 595 uint32_t io_flags) 596 { 597 struct nvme_request *req; 598 struct nvme_payload payload; 599 600 payload = NVME_PAYLOAD_CONTIG(buffer, NULL); 601 602 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ, 603 io_flags, 0, 604 0, true); 605 if (req != NULL) { 606 return nvme_qpair_submit_request(qpair, req); 607 } else if (spdk_nvme_ns_check_request_length(lba_count, 608 ns->sectors_per_max_io, 609 ns->sectors_per_stripe, 610 qpair->ctrlr->opts.io_queue_requests)) { 611 return -EINVAL; 612 } else { 613 return -ENOMEM; 614 } 615 } 616 617 int 618 spdk_nvme_ns_cmd_read_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, void *buffer, 619 void *metadata, 620 uint64_t lba, 621 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, 622 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag) 623 { 624 struct nvme_request *req; 625 struct nvme_payload payload; 626 627 payload = NVME_PAYLOAD_CONTIG(buffer, metadata); 628 629 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ, 630 io_flags, 631 apptag_mask, apptag, true); 632 if (req != NULL) { 633 return nvme_qpair_submit_request(qpair, req); 634 } else if (spdk_nvme_ns_check_request_length(lba_count, 635 ns->sectors_per_max_io, 636 ns->sectors_per_stripe, 637 qpair->ctrlr->opts.io_queue_requests)) { 638 return -EINVAL; 639 } else { 640 return -ENOMEM; 641 } 642 } 643 644 int 645 spdk_nvme_ns_cmd_readv(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 646 uint64_t lba, uint32_t lba_count, 647 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags, 648 spdk_nvme_req_reset_sgl_cb reset_sgl_fn, 649 spdk_nvme_req_next_sge_cb next_sge_fn) 650 { 651 struct nvme_request *req; 652 struct nvme_payload payload; 653 654 if (reset_sgl_fn == NULL || next_sge_fn == NULL) { 655 return -EINVAL; 656 } 657 658 payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL); 659 660 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ, 661 io_flags, 0, 0, true); 662 if (req != NULL) { 663 return nvme_qpair_submit_request(qpair, req); 664 } else if (spdk_nvme_ns_check_request_length(lba_count, 665 ns->sectors_per_max_io, 666 ns->sectors_per_stripe, 667 qpair->ctrlr->opts.io_queue_requests)) { 668 return -EINVAL; 669 } else { 670 return -ENOMEM; 671 } 672 } 673 674 int 675 spdk_nvme_ns_cmd_readv_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 676 uint64_t lba, uint32_t lba_count, 677 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags, 678 spdk_nvme_req_reset_sgl_cb reset_sgl_fn, 679 spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata, 680 uint16_t apptag_mask, uint16_t apptag) 681 { 682 struct nvme_request *req; 683 struct nvme_payload payload; 684 685 if (reset_sgl_fn == NULL || next_sge_fn == NULL) { 686 return -EINVAL; 687 } 688 689 payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata); 690 691 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_READ, 692 io_flags, apptag_mask, apptag, true); 693 if (req != NULL) { 694 return nvme_qpair_submit_request(qpair, req); 695 } else if (spdk_nvme_ns_check_request_length(lba_count, 696 ns->sectors_per_max_io, 697 ns->sectors_per_stripe, 698 qpair->ctrlr->opts.io_queue_requests)) { 699 return -EINVAL; 700 } else { 701 return -ENOMEM; 702 } 703 } 704 705 int 706 spdk_nvme_ns_cmd_write(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 707 void *buffer, uint64_t lba, 708 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, 709 uint32_t io_flags) 710 { 711 struct nvme_request *req; 712 struct nvme_payload payload; 713 714 payload = NVME_PAYLOAD_CONTIG(buffer, NULL); 715 716 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE, 717 io_flags, 0, 0, true); 718 if (req != NULL) { 719 return nvme_qpair_submit_request(qpair, req); 720 } else if (spdk_nvme_ns_check_request_length(lba_count, 721 ns->sectors_per_max_io, 722 ns->sectors_per_stripe, 723 qpair->ctrlr->opts.io_queue_requests)) { 724 return -EINVAL; 725 } else { 726 return -ENOMEM; 727 } 728 } 729 730 int 731 spdk_nvme_ns_cmd_write_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 732 void *buffer, void *metadata, uint64_t lba, 733 uint32_t lba_count, spdk_nvme_cmd_cb cb_fn, void *cb_arg, 734 uint32_t io_flags, uint16_t apptag_mask, uint16_t apptag) 735 { 736 struct nvme_request *req; 737 struct nvme_payload payload; 738 739 payload = NVME_PAYLOAD_CONTIG(buffer, metadata); 740 741 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE, 742 io_flags, apptag_mask, apptag, true); 743 if (req != NULL) { 744 return nvme_qpair_submit_request(qpair, req); 745 } else if (spdk_nvme_ns_check_request_length(lba_count, 746 ns->sectors_per_max_io, 747 ns->sectors_per_stripe, 748 qpair->ctrlr->opts.io_queue_requests)) { 749 return -EINVAL; 750 } else { 751 return -ENOMEM; 752 } 753 } 754 755 int 756 spdk_nvme_ns_cmd_writev(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 757 uint64_t lba, uint32_t lba_count, 758 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags, 759 spdk_nvme_req_reset_sgl_cb reset_sgl_fn, 760 spdk_nvme_req_next_sge_cb next_sge_fn) 761 { 762 struct nvme_request *req; 763 struct nvme_payload payload; 764 765 if (reset_sgl_fn == NULL || next_sge_fn == NULL) { 766 return -EINVAL; 767 } 768 769 payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, NULL); 770 771 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE, 772 io_flags, 0, 0, true); 773 if (req != NULL) { 774 return nvme_qpair_submit_request(qpair, req); 775 } else if (spdk_nvme_ns_check_request_length(lba_count, 776 ns->sectors_per_max_io, 777 ns->sectors_per_stripe, 778 qpair->ctrlr->opts.io_queue_requests)) { 779 return -EINVAL; 780 } else { 781 return -ENOMEM; 782 } 783 } 784 785 int 786 spdk_nvme_ns_cmd_writev_with_md(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 787 uint64_t lba, uint32_t lba_count, 788 spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t io_flags, 789 spdk_nvme_req_reset_sgl_cb reset_sgl_fn, 790 spdk_nvme_req_next_sge_cb next_sge_fn, void *metadata, 791 uint16_t apptag_mask, uint16_t apptag) 792 { 793 struct nvme_request *req; 794 struct nvme_payload payload; 795 796 if (reset_sgl_fn == NULL || next_sge_fn == NULL) { 797 return -EINVAL; 798 } 799 800 payload = NVME_PAYLOAD_SGL(reset_sgl_fn, next_sge_fn, cb_arg, metadata); 801 802 req = _nvme_ns_cmd_rw(ns, qpair, &payload, 0, 0, lba, lba_count, cb_fn, cb_arg, SPDK_NVME_OPC_WRITE, 803 io_flags, apptag_mask, apptag, true); 804 if (req != NULL) { 805 return nvme_qpair_submit_request(qpair, req); 806 } else if (spdk_nvme_ns_check_request_length(lba_count, 807 ns->sectors_per_max_io, 808 ns->sectors_per_stripe, 809 qpair->ctrlr->opts.io_queue_requests)) { 810 return -EINVAL; 811 } else { 812 return -ENOMEM; 813 } 814 } 815 816 int 817 spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 818 uint64_t lba, uint32_t lba_count, 819 spdk_nvme_cmd_cb cb_fn, void *cb_arg, 820 uint32_t io_flags) 821 { 822 struct nvme_request *req; 823 struct spdk_nvme_cmd *cmd; 824 uint64_t *tmp_lba; 825 826 if (lba_count == 0 || lba_count > UINT16_MAX + 1) { 827 return -EINVAL; 828 } 829 830 req = nvme_allocate_request_null(qpair, cb_fn, cb_arg); 831 if (req == NULL) { 832 return -ENOMEM; 833 } 834 835 cmd = &req->cmd; 836 cmd->opc = SPDK_NVME_OPC_WRITE_ZEROES; 837 cmd->nsid = ns->id; 838 839 tmp_lba = (uint64_t *)&cmd->cdw10; 840 *tmp_lba = lba; 841 cmd->cdw12 = lba_count - 1; 842 cmd->cdw12 |= io_flags; 843 844 return nvme_qpair_submit_request(qpair, req); 845 } 846 847 int 848 spdk_nvme_ns_cmd_dataset_management(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 849 uint32_t type, 850 const struct spdk_nvme_dsm_range *ranges, uint16_t num_ranges, 851 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 852 { 853 struct nvme_request *req; 854 struct spdk_nvme_cmd *cmd; 855 856 if (num_ranges == 0 || num_ranges > SPDK_NVME_DATASET_MANAGEMENT_MAX_RANGES) { 857 return -EINVAL; 858 } 859 860 if (ranges == NULL) { 861 return -EINVAL; 862 } 863 864 req = nvme_allocate_request_user_copy(qpair, (void *)ranges, 865 num_ranges * sizeof(struct spdk_nvme_dsm_range), 866 cb_fn, cb_arg, true); 867 if (req == NULL) { 868 return -ENOMEM; 869 } 870 871 cmd = &req->cmd; 872 cmd->opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; 873 cmd->nsid = ns->id; 874 875 cmd->cdw10 = num_ranges - 1; 876 cmd->cdw11 = type; 877 878 return nvme_qpair_submit_request(qpair, req); 879 } 880 881 int 882 spdk_nvme_ns_cmd_flush(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *qpair, 883 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 884 { 885 struct nvme_request *req; 886 struct spdk_nvme_cmd *cmd; 887 888 req = nvme_allocate_request_null(qpair, cb_fn, cb_arg); 889 if (req == NULL) { 890 return -ENOMEM; 891 } 892 893 cmd = &req->cmd; 894 cmd->opc = SPDK_NVME_OPC_FLUSH; 895 cmd->nsid = ns->id; 896 897 return nvme_qpair_submit_request(qpair, req); 898 } 899 900 int 901 spdk_nvme_ns_cmd_reservation_register(struct spdk_nvme_ns *ns, 902 struct spdk_nvme_qpair *qpair, 903 struct spdk_nvme_reservation_register_data *payload, 904 bool ignore_key, 905 enum spdk_nvme_reservation_register_action action, 906 enum spdk_nvme_reservation_register_cptpl cptpl, 907 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 908 { 909 struct nvme_request *req; 910 struct spdk_nvme_cmd *cmd; 911 912 req = nvme_allocate_request_user_copy(qpair, 913 payload, sizeof(struct spdk_nvme_reservation_register_data), 914 cb_fn, cb_arg, true); 915 if (req == NULL) { 916 return -ENOMEM; 917 } 918 919 cmd = &req->cmd; 920 cmd->opc = SPDK_NVME_OPC_RESERVATION_REGISTER; 921 cmd->nsid = ns->id; 922 923 /* Bits 0-2 */ 924 cmd->cdw10 = action; 925 /* Bit 3 */ 926 cmd->cdw10 |= ignore_key ? 1 << 3 : 0; 927 /* Bits 30-31 */ 928 cmd->cdw10 |= (uint32_t)cptpl << 30; 929 930 return nvme_qpair_submit_request(qpair, req); 931 } 932 933 int 934 spdk_nvme_ns_cmd_reservation_release(struct spdk_nvme_ns *ns, 935 struct spdk_nvme_qpair *qpair, 936 struct spdk_nvme_reservation_key_data *payload, 937 bool ignore_key, 938 enum spdk_nvme_reservation_release_action action, 939 enum spdk_nvme_reservation_type type, 940 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 941 { 942 struct nvme_request *req; 943 struct spdk_nvme_cmd *cmd; 944 945 req = nvme_allocate_request_user_copy(qpair, 946 payload, sizeof(struct spdk_nvme_reservation_key_data), cb_fn, 947 cb_arg, true); 948 if (req == NULL) { 949 return -ENOMEM; 950 } 951 952 cmd = &req->cmd; 953 cmd->opc = SPDK_NVME_OPC_RESERVATION_RELEASE; 954 cmd->nsid = ns->id; 955 956 /* Bits 0-2 */ 957 cmd->cdw10 = action; 958 /* Bit 3 */ 959 cmd->cdw10 |= ignore_key ? 1 << 3 : 0; 960 /* Bits 8-15 */ 961 cmd->cdw10 |= (uint32_t)type << 8; 962 963 return nvme_qpair_submit_request(qpair, req); 964 } 965 966 int 967 spdk_nvme_ns_cmd_reservation_acquire(struct spdk_nvme_ns *ns, 968 struct spdk_nvme_qpair *qpair, 969 struct spdk_nvme_reservation_acquire_data *payload, 970 bool ignore_key, 971 enum spdk_nvme_reservation_acquire_action action, 972 enum spdk_nvme_reservation_type type, 973 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 974 { 975 struct nvme_request *req; 976 struct spdk_nvme_cmd *cmd; 977 978 req = nvme_allocate_request_user_copy(qpair, 979 payload, sizeof(struct spdk_nvme_reservation_acquire_data), 980 cb_fn, cb_arg, true); 981 if (req == NULL) { 982 return -ENOMEM; 983 } 984 985 cmd = &req->cmd; 986 cmd->opc = SPDK_NVME_OPC_RESERVATION_ACQUIRE; 987 cmd->nsid = ns->id; 988 989 /* Bits 0-2 */ 990 cmd->cdw10 = action; 991 /* Bit 3 */ 992 cmd->cdw10 |= ignore_key ? 1 << 3 : 0; 993 /* Bits 8-15 */ 994 cmd->cdw10 |= (uint32_t)type << 8; 995 996 return nvme_qpair_submit_request(qpair, req); 997 } 998 999 int 1000 spdk_nvme_ns_cmd_reservation_report(struct spdk_nvme_ns *ns, 1001 struct spdk_nvme_qpair *qpair, 1002 void *payload, uint32_t len, 1003 spdk_nvme_cmd_cb cb_fn, void *cb_arg) 1004 { 1005 uint32_t num_dwords; 1006 struct nvme_request *req; 1007 struct spdk_nvme_cmd *cmd; 1008 1009 if (len % 4) { 1010 return -EINVAL; 1011 } 1012 num_dwords = len / 4; 1013 1014 req = nvme_allocate_request_user_copy(qpair, payload, len, cb_fn, cb_arg, false); 1015 if (req == NULL) { 1016 return -ENOMEM; 1017 } 1018 1019 cmd = &req->cmd; 1020 cmd->opc = SPDK_NVME_OPC_RESERVATION_REPORT; 1021 cmd->nsid = ns->id; 1022 1023 cmd->cdw10 = num_dwords; 1024 1025 return nvme_qpair_submit_request(qpair, req); 1026 } 1027