1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 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 "spdk/stdinc.h" 35 36 #include "nvmf_internal.h" 37 38 #include "spdk/bdev.h" 39 #include "spdk/endian.h" 40 #include "spdk/thread.h" 41 #include "spdk/likely.h" 42 #include "spdk/nvme.h" 43 #include "spdk/nvmf_cmd.h" 44 #include "spdk/nvmf_spec.h" 45 #include "spdk/trace.h" 46 #include "spdk/scsi_spec.h" 47 #include "spdk/string.h" 48 #include "spdk/util.h" 49 50 #include "spdk_internal/log.h" 51 52 static bool 53 spdk_nvmf_subsystem_bdev_io_type_supported(struct spdk_nvmf_subsystem *subsystem, 54 enum spdk_bdev_io_type io_type) 55 { 56 struct spdk_nvmf_ns *ns; 57 58 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; 59 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { 60 if (ns->bdev == NULL) { 61 continue; 62 } 63 64 if (!spdk_bdev_io_type_supported(ns->bdev, io_type)) { 65 SPDK_DEBUGLOG(SPDK_LOG_NVMF, 66 "Subsystem %s namespace %u (%s) does not support io_type %d\n", 67 spdk_nvmf_subsystem_get_nqn(subsystem), 68 ns->opts.nsid, spdk_bdev_get_name(ns->bdev), (int)io_type); 69 return false; 70 } 71 } 72 73 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "All devices in Subsystem %s support io_type %d\n", 74 spdk_nvmf_subsystem_get_nqn(subsystem), (int)io_type); 75 return true; 76 } 77 78 bool 79 spdk_nvmf_ctrlr_dsm_supported(struct spdk_nvmf_ctrlr *ctrlr) 80 { 81 return spdk_nvmf_subsystem_bdev_io_type_supported(ctrlr->subsys, SPDK_BDEV_IO_TYPE_UNMAP); 82 } 83 84 bool 85 spdk_nvmf_ctrlr_write_zeroes_supported(struct spdk_nvmf_ctrlr *ctrlr) 86 { 87 return spdk_nvmf_subsystem_bdev_io_type_supported(ctrlr->subsys, SPDK_BDEV_IO_TYPE_WRITE_ZEROES); 88 } 89 90 static void 91 nvmf_bdev_ctrlr_complete_cmd(struct spdk_bdev_io *bdev_io, bool success, 92 void *cb_arg) 93 { 94 struct spdk_nvmf_request *req = cb_arg; 95 struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; 96 int first_sc, first_sct, second_sc, second_sct; 97 uint32_t cdw0; 98 struct spdk_nvmf_request *first_req = req->first_fused_req; 99 100 if (spdk_unlikely(first_req != NULL)) { 101 /* fused commands - get status for both operations */ 102 struct spdk_nvme_cpl *fused_response = &first_req->rsp->nvme_cpl; 103 104 spdk_bdev_io_get_nvme_fused_status(bdev_io, &cdw0, &second_sct, &second_sc, &first_sct, &first_sc); 105 fused_response->cdw0 = cdw0; 106 fused_response->status.sc = second_sc; 107 fused_response->status.sct = second_sct; 108 109 /* first request should be completed */ 110 spdk_nvmf_request_complete(first_req); 111 req->first_fused_req = NULL; 112 } else { 113 spdk_bdev_io_get_nvme_status(bdev_io, &cdw0, &first_sct, &first_sc); 114 } 115 116 response->cdw0 = cdw0; 117 response->status.sc = first_sc; 118 response->status.sct = first_sct; 119 120 spdk_nvmf_request_complete(req); 121 spdk_bdev_free_io(bdev_io); 122 } 123 124 static void 125 nvmf_bdev_ctrlr_complete_admin_cmd(struct spdk_bdev_io *bdev_io, bool success, 126 void *cb_arg) 127 { 128 struct spdk_nvmf_request *req = cb_arg; 129 130 if (req->cmd_cb_fn) { 131 req->cmd_cb_fn(req); 132 } 133 134 nvmf_bdev_ctrlr_complete_cmd(bdev_io, success, req); 135 } 136 137 void 138 spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata, 139 bool dif_insert_or_strip) 140 { 141 struct spdk_bdev *bdev = ns->bdev; 142 uint64_t num_blocks; 143 144 num_blocks = spdk_bdev_get_num_blocks(bdev); 145 146 nsdata->nsze = num_blocks; 147 nsdata->ncap = num_blocks; 148 nsdata->nuse = num_blocks; 149 nsdata->nlbaf = 0; 150 nsdata->flbas.format = 0; 151 nsdata->nacwu = spdk_bdev_get_acwu(bdev); 152 if (!dif_insert_or_strip) { 153 nsdata->lbaf[0].ms = spdk_bdev_get_md_size(bdev); 154 nsdata->lbaf[0].lbads = spdk_u32log2(spdk_bdev_get_block_size(bdev)); 155 if (nsdata->lbaf[0].ms != 0) { 156 nsdata->flbas.extended = 1; 157 nsdata->mc.extended = 1; 158 nsdata->mc.pointer = 0; 159 nsdata->dps.md_start = spdk_bdev_is_dif_head_of_md(bdev); 160 161 switch (spdk_bdev_get_dif_type(bdev)) { 162 case SPDK_DIF_TYPE1: 163 nsdata->dpc.pit1 = 1; 164 nsdata->dps.pit = SPDK_NVME_FMT_NVM_PROTECTION_TYPE1; 165 break; 166 case SPDK_DIF_TYPE2: 167 nsdata->dpc.pit2 = 1; 168 nsdata->dps.pit = SPDK_NVME_FMT_NVM_PROTECTION_TYPE2; 169 break; 170 case SPDK_DIF_TYPE3: 171 nsdata->dpc.pit3 = 1; 172 nsdata->dps.pit = SPDK_NVME_FMT_NVM_PROTECTION_TYPE3; 173 break; 174 default: 175 SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Protection Disabled\n"); 176 nsdata->dps.pit = SPDK_NVME_FMT_NVM_PROTECTION_DISABLE; 177 break; 178 } 179 } 180 } else { 181 nsdata->lbaf[0].ms = 0; 182 nsdata->lbaf[0].lbads = spdk_u32log2(spdk_bdev_get_data_block_size(bdev)); 183 } 184 nsdata->noiob = spdk_bdev_get_optimal_io_boundary(bdev); 185 nsdata->nmic.can_share = 1; 186 if (ns->ptpl_file != NULL) { 187 nsdata->nsrescap.rescap.persist = 1; 188 } 189 nsdata->nsrescap.rescap.write_exclusive = 1; 190 nsdata->nsrescap.rescap.exclusive_access = 1; 191 nsdata->nsrescap.rescap.write_exclusive_reg_only = 1; 192 nsdata->nsrescap.rescap.exclusive_access_reg_only = 1; 193 nsdata->nsrescap.rescap.write_exclusive_all_reg = 1; 194 nsdata->nsrescap.rescap.exclusive_access_all_reg = 1; 195 nsdata->nsrescap.rescap.ignore_existing_key = 1; 196 197 SPDK_STATIC_ASSERT(sizeof(nsdata->nguid) == sizeof(ns->opts.nguid), "size mismatch"); 198 memcpy(nsdata->nguid, ns->opts.nguid, sizeof(nsdata->nguid)); 199 200 SPDK_STATIC_ASSERT(sizeof(nsdata->eui64) == sizeof(ns->opts.eui64), "size mismatch"); 201 memcpy(&nsdata->eui64, ns->opts.eui64, sizeof(nsdata->eui64)); 202 } 203 204 static void 205 nvmf_bdev_ctrlr_get_rw_params(const struct spdk_nvme_cmd *cmd, uint64_t *start_lba, 206 uint64_t *num_blocks) 207 { 208 /* SLBA: CDW10 and CDW11 */ 209 *start_lba = from_le64(&cmd->cdw10); 210 211 /* NLB: CDW12 bits 15:00, 0's based */ 212 *num_blocks = (from_le32(&cmd->cdw12) & 0xFFFFu) + 1; 213 } 214 215 static bool 216 nvmf_bdev_ctrlr_lba_in_range(uint64_t bdev_num_blocks, uint64_t io_start_lba, 217 uint64_t io_num_blocks) 218 { 219 if (io_start_lba + io_num_blocks > bdev_num_blocks || 220 io_start_lba + io_num_blocks < io_start_lba) { 221 return false; 222 } 223 224 return true; 225 } 226 227 static void 228 spdk_nvmf_ctrlr_process_io_cmd_resubmit(void *arg) 229 { 230 struct spdk_nvmf_request *req = arg; 231 232 spdk_nvmf_ctrlr_process_io_cmd(req); 233 } 234 235 static void 236 spdk_nvmf_ctrlr_process_admin_cmd_resubmit(void *arg) 237 { 238 struct spdk_nvmf_request *req = arg; 239 240 spdk_nvmf_ctrlr_process_admin_cmd(req); 241 } 242 243 static void 244 nvmf_bdev_ctrl_queue_io(struct spdk_nvmf_request *req, struct spdk_bdev *bdev, 245 struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn, void *cb_arg) 246 { 247 int rc; 248 249 req->bdev_io_wait.bdev = bdev; 250 req->bdev_io_wait.cb_fn = cb_fn; 251 req->bdev_io_wait.cb_arg = cb_arg; 252 253 rc = spdk_bdev_queue_io_wait(bdev, ch, &req->bdev_io_wait); 254 if (rc != 0) { 255 assert(false); 256 } 257 req->qpair->group->stat.pending_bdev_io++; 258 } 259 260 int 261 spdk_nvmf_bdev_ctrlr_read_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 262 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 263 { 264 uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev); 265 uint32_t block_size = spdk_bdev_get_block_size(bdev); 266 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 267 struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl; 268 uint64_t start_lba; 269 uint64_t num_blocks; 270 int rc; 271 272 nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks); 273 274 if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) { 275 SPDK_ERRLOG("end of media\n"); 276 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 277 rsp->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE; 278 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 279 } 280 281 if (spdk_unlikely(num_blocks * block_size > req->length)) { 282 SPDK_ERRLOG("Read NLB %" PRIu64 " * block size %" PRIu32 " > SGL length %" PRIu32 "\n", 283 num_blocks, block_size, req->length); 284 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 285 rsp->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID; 286 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 287 } 288 289 rc = spdk_bdev_readv_blocks(desc, ch, req->iov, req->iovcnt, start_lba, num_blocks, 290 nvmf_bdev_ctrlr_complete_cmd, req); 291 if (spdk_unlikely(rc)) { 292 if (rc == -ENOMEM) { 293 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); 294 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 295 } 296 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 297 rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 298 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 299 } 300 301 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 302 } 303 304 int 305 spdk_nvmf_bdev_ctrlr_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 306 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 307 { 308 uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev); 309 uint32_t block_size = spdk_bdev_get_block_size(bdev); 310 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 311 struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl; 312 uint64_t start_lba; 313 uint64_t num_blocks; 314 int rc; 315 316 nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks); 317 318 if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) { 319 SPDK_ERRLOG("end of media\n"); 320 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 321 rsp->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE; 322 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 323 } 324 325 if (spdk_unlikely(num_blocks * block_size > req->length)) { 326 SPDK_ERRLOG("Write NLB %" PRIu64 " * block size %" PRIu32 " > SGL length %" PRIu32 "\n", 327 num_blocks, block_size, req->length); 328 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 329 rsp->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID; 330 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 331 } 332 333 rc = spdk_bdev_writev_blocks(desc, ch, req->iov, req->iovcnt, start_lba, num_blocks, 334 nvmf_bdev_ctrlr_complete_cmd, req); 335 if (spdk_unlikely(rc)) { 336 if (rc == -ENOMEM) { 337 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); 338 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 339 } 340 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 341 rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 342 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 343 } 344 345 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 346 } 347 348 int 349 spdk_nvmf_bdev_ctrlr_compare_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 350 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 351 { 352 uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev); 353 uint32_t block_size = spdk_bdev_get_block_size(bdev); 354 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 355 struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl; 356 uint64_t start_lba; 357 uint64_t num_blocks; 358 int rc; 359 360 nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks); 361 362 if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) { 363 SPDK_ERRLOG("end of media\n"); 364 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 365 rsp->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE; 366 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 367 } 368 369 if (spdk_unlikely(num_blocks * block_size > req->length)) { 370 SPDK_ERRLOG("Compare NLB %" PRIu64 " * block size %" PRIu32 " > SGL length %" PRIu32 "\n", 371 num_blocks, block_size, req->length); 372 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 373 rsp->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID; 374 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 375 } 376 377 rc = spdk_bdev_comparev_blocks(desc, ch, req->iov, req->iovcnt, start_lba, num_blocks, 378 nvmf_bdev_ctrlr_complete_cmd, req); 379 if (spdk_unlikely(rc)) { 380 if (rc == -ENOMEM) { 381 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); 382 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 383 } 384 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 385 rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 386 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 387 } 388 389 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 390 } 391 392 int 393 spdk_nvmf_bdev_ctrlr_compare_and_write_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 394 struct spdk_io_channel *ch, struct spdk_nvmf_request *cmp_req, struct spdk_nvmf_request *write_req) 395 { 396 uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev); 397 uint32_t block_size = spdk_bdev_get_block_size(bdev); 398 struct spdk_nvme_cmd *cmp_cmd = &cmp_req->cmd->nvme_cmd; 399 struct spdk_nvme_cmd *write_cmd = &write_req->cmd->nvme_cmd; 400 struct spdk_nvme_cpl *rsp = &write_req->rsp->nvme_cpl; 401 uint64_t write_start_lba, cmp_start_lba; 402 uint64_t write_num_blocks, cmp_num_blocks; 403 int rc; 404 405 nvmf_bdev_ctrlr_get_rw_params(cmp_cmd, &cmp_start_lba, &cmp_num_blocks); 406 nvmf_bdev_ctrlr_get_rw_params(write_cmd, &write_start_lba, &write_num_blocks); 407 408 if (spdk_unlikely(write_start_lba != cmp_start_lba || write_num_blocks != cmp_num_blocks)) { 409 SPDK_ERRLOG("Fused command start lba / num blocks mismatch\n"); 410 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 411 rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD; 412 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 413 } 414 415 if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, write_start_lba, 416 write_num_blocks))) { 417 SPDK_ERRLOG("end of media\n"); 418 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 419 rsp->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE; 420 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 421 } 422 423 if (spdk_unlikely(write_num_blocks * block_size > write_req->length)) { 424 SPDK_ERRLOG("Write NLB %" PRIu64 " * block size %" PRIu32 " > SGL length %" PRIu32 "\n", 425 write_num_blocks, block_size, write_req->length); 426 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 427 rsp->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID; 428 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 429 } 430 431 rc = spdk_bdev_comparev_and_writev_blocks(desc, ch, cmp_req->iov, cmp_req->iovcnt, write_req->iov, 432 write_req->iovcnt, write_start_lba, write_num_blocks, nvmf_bdev_ctrlr_complete_cmd, write_req); 433 if (spdk_unlikely(rc)) { 434 if (rc == -ENOMEM) { 435 nvmf_bdev_ctrl_queue_io(cmp_req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, cmp_req); 436 nvmf_bdev_ctrl_queue_io(write_req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, write_req); 437 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 438 } 439 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 440 rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 441 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 442 } 443 444 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 445 } 446 447 int 448 spdk_nvmf_bdev_ctrlr_write_zeroes_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 449 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 450 { 451 uint64_t bdev_num_blocks = spdk_bdev_get_num_blocks(bdev); 452 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 453 struct spdk_nvme_cpl *rsp = &req->rsp->nvme_cpl; 454 uint64_t start_lba; 455 uint64_t num_blocks; 456 int rc; 457 458 nvmf_bdev_ctrlr_get_rw_params(cmd, &start_lba, &num_blocks); 459 460 if (spdk_unlikely(!nvmf_bdev_ctrlr_lba_in_range(bdev_num_blocks, start_lba, num_blocks))) { 461 SPDK_ERRLOG("end of media\n"); 462 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 463 rsp->status.sc = SPDK_NVME_SC_LBA_OUT_OF_RANGE; 464 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 465 } 466 467 rc = spdk_bdev_write_zeroes_blocks(desc, ch, start_lba, num_blocks, 468 nvmf_bdev_ctrlr_complete_cmd, req); 469 if (spdk_unlikely(rc)) { 470 if (rc == -ENOMEM) { 471 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); 472 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 473 } 474 rsp->status.sct = SPDK_NVME_SCT_GENERIC; 475 rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 476 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 477 } 478 479 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 480 } 481 482 int 483 spdk_nvmf_bdev_ctrlr_flush_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 484 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 485 { 486 struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; 487 int rc; 488 489 /* As for NVMeoF controller, SPDK always set volatile write 490 * cache bit to 1, return success for those block devices 491 * which can't support FLUSH command. 492 */ 493 if (!spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_FLUSH)) { 494 response->status.sct = SPDK_NVME_SCT_GENERIC; 495 response->status.sc = SPDK_NVME_SC_SUCCESS; 496 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 497 } 498 499 rc = spdk_bdev_flush_blocks(desc, ch, 0, spdk_bdev_get_num_blocks(bdev), 500 nvmf_bdev_ctrlr_complete_cmd, req); 501 if (spdk_unlikely(rc)) { 502 if (rc == -ENOMEM) { 503 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); 504 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 505 } 506 response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 507 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 508 } 509 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 510 } 511 512 struct nvmf_bdev_ctrlr_unmap { 513 struct spdk_nvmf_request *req; 514 uint32_t count; 515 struct spdk_bdev_desc *desc; 516 struct spdk_bdev *bdev; 517 struct spdk_io_channel *ch; 518 uint32_t range_index; 519 }; 520 521 static void 522 nvmf_bdev_ctrlr_unmap_cpl(struct spdk_bdev_io *bdev_io, bool success, 523 void *cb_arg) 524 { 525 struct nvmf_bdev_ctrlr_unmap *unmap_ctx = cb_arg; 526 struct spdk_nvmf_request *req = unmap_ctx->req; 527 struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; 528 int sc, sct; 529 uint32_t cdw0; 530 531 unmap_ctx->count--; 532 533 if (response->status.sct == SPDK_NVME_SCT_GENERIC && 534 response->status.sc == SPDK_NVME_SC_SUCCESS) { 535 spdk_bdev_io_get_nvme_status(bdev_io, &cdw0, &sct, &sc); 536 response->cdw0 = cdw0; 537 response->status.sc = sc; 538 response->status.sct = sct; 539 } 540 541 if (unmap_ctx->count == 0) { 542 spdk_nvmf_request_complete(req); 543 free(unmap_ctx); 544 } 545 spdk_bdev_free_io(bdev_io); 546 } 547 548 static int 549 nvmf_bdev_ctrlr_unmap(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 550 struct spdk_io_channel *ch, struct spdk_nvmf_request *req, 551 struct nvmf_bdev_ctrlr_unmap *unmap_ctx); 552 static void 553 nvmf_bdev_ctrlr_unmap_resubmit(void *arg) 554 { 555 struct nvmf_bdev_ctrlr_unmap *unmap_ctx = arg; 556 struct spdk_nvmf_request *req = unmap_ctx->req; 557 struct spdk_bdev_desc *desc = unmap_ctx->desc; 558 struct spdk_bdev *bdev = unmap_ctx->bdev; 559 struct spdk_io_channel *ch = unmap_ctx->ch; 560 561 nvmf_bdev_ctrlr_unmap(bdev, desc, ch, req, unmap_ctx); 562 } 563 564 static int 565 nvmf_bdev_ctrlr_unmap(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 566 struct spdk_io_channel *ch, struct spdk_nvmf_request *req, 567 struct nvmf_bdev_ctrlr_unmap *unmap_ctx) 568 { 569 uint16_t nr, i; 570 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 571 struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; 572 struct spdk_nvme_dsm_range *dsm_range; 573 uint64_t lba; 574 uint32_t lba_count; 575 int rc; 576 577 nr = cmd->cdw10_bits.dsm.nr + 1; 578 if (nr * sizeof(struct spdk_nvme_dsm_range) > req->length) { 579 SPDK_ERRLOG("Dataset Management number of ranges > SGL length\n"); 580 response->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID; 581 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 582 } 583 584 if (unmap_ctx == NULL) { 585 unmap_ctx = calloc(1, sizeof(*unmap_ctx)); 586 if (!unmap_ctx) { 587 response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 588 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 589 } 590 591 unmap_ctx->req = req; 592 unmap_ctx->desc = desc; 593 unmap_ctx->ch = ch; 594 unmap_ctx->bdev = bdev; 595 596 response->status.sct = SPDK_NVME_SCT_GENERIC; 597 response->status.sc = SPDK_NVME_SC_SUCCESS; 598 } else { 599 unmap_ctx->count--; /* dequeued */ 600 } 601 602 dsm_range = (struct spdk_nvme_dsm_range *)req->data; 603 for (i = unmap_ctx->range_index; i < nr; i++) { 604 lba = dsm_range[i].starting_lba; 605 lba_count = dsm_range[i].length; 606 607 unmap_ctx->count++; 608 609 rc = spdk_bdev_unmap_blocks(desc, ch, lba, lba_count, 610 nvmf_bdev_ctrlr_unmap_cpl, unmap_ctx); 611 if (rc) { 612 if (rc == -ENOMEM) { 613 nvmf_bdev_ctrl_queue_io(req, bdev, ch, nvmf_bdev_ctrlr_unmap_resubmit, unmap_ctx); 614 /* Unmap was not yet submitted to bdev */ 615 /* unmap_ctx->count will be decremented when the request is dequeued */ 616 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 617 } 618 response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 619 unmap_ctx->count--; 620 /* We can't return here - we may have to wait for any other 621 * unmaps already sent to complete */ 622 break; 623 } 624 unmap_ctx->range_index++; 625 } 626 627 if (unmap_ctx->count == 0) { 628 free(unmap_ctx); 629 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 630 } 631 632 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 633 } 634 635 int 636 spdk_nvmf_bdev_ctrlr_dsm_cmd(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 637 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 638 { 639 struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; 640 struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; 641 642 if (cmd->cdw11_bits.dsm.ad) { 643 return nvmf_bdev_ctrlr_unmap(bdev, desc, ch, req, NULL); 644 } 645 646 response->status.sct = SPDK_NVME_SCT_GENERIC; 647 response->status.sc = SPDK_NVME_SC_SUCCESS; 648 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 649 } 650 651 int 652 spdk_nvmf_bdev_ctrlr_nvme_passthru_io(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 653 struct spdk_io_channel *ch, struct spdk_nvmf_request *req) 654 { 655 int rc; 656 657 rc = spdk_bdev_nvme_io_passthru(desc, ch, &req->cmd->nvme_cmd, req->data, req->length, 658 nvmf_bdev_ctrlr_complete_cmd, req); 659 if (spdk_unlikely(rc)) { 660 if (rc == -ENOMEM) { 661 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_io_cmd_resubmit, req); 662 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 663 } 664 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 665 req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_OPCODE; 666 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 667 } 668 669 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 670 } 671 672 int 673 spdk_nvmf_bdev_ctrlr_nvme_passthru_admin(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, 674 struct spdk_io_channel *ch, struct spdk_nvmf_request *req, 675 spdk_nvmf_nvme_passthru_cmd_cb cb_fn) 676 { 677 int rc; 678 679 req->cmd_cb_fn = cb_fn; 680 681 rc = spdk_bdev_nvme_admin_passthru(desc, ch, &req->cmd->nvme_cmd, req->data, req->length, 682 nvmf_bdev_ctrlr_complete_admin_cmd, req); 683 if (spdk_unlikely(rc)) { 684 if (rc == -ENOMEM) { 685 nvmf_bdev_ctrl_queue_io(req, bdev, ch, spdk_nvmf_ctrlr_process_admin_cmd_resubmit, req); 686 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 687 } 688 req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC; 689 req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; 690 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 691 } 692 693 return SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS; 694 } 695 696 bool 697 spdk_nvmf_bdev_ctrlr_get_dif_ctx(struct spdk_bdev *bdev, struct spdk_nvme_cmd *cmd, 698 struct spdk_dif_ctx *dif_ctx) 699 { 700 uint32_t init_ref_tag, dif_check_flags = 0; 701 int rc; 702 703 if (spdk_bdev_get_md_size(bdev) == 0) { 704 return false; 705 } 706 707 /* Initial Reference Tag is the lower 32 bits of the start LBA. */ 708 init_ref_tag = (uint32_t)from_le64(&cmd->cdw10); 709 710 if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_REFTAG)) { 711 dif_check_flags |= SPDK_DIF_FLAGS_REFTAG_CHECK; 712 } 713 714 if (spdk_bdev_is_dif_check_enabled(bdev, SPDK_DIF_CHECK_TYPE_GUARD)) { 715 dif_check_flags |= SPDK_DIF_FLAGS_GUARD_CHECK; 716 } 717 718 rc = spdk_dif_ctx_init(dif_ctx, 719 spdk_bdev_get_block_size(bdev), 720 spdk_bdev_get_md_size(bdev), 721 spdk_bdev_is_md_interleaved(bdev), 722 spdk_bdev_is_dif_head_of_md(bdev), 723 spdk_bdev_get_dif_type(bdev), 724 dif_check_flags, 725 init_ref_tag, 0, 0, 0, 0); 726 727 return (rc == 0) ? true : false; 728 } 729