1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2019 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #define FUSE_USE_VERSION 31 7 8 #include <fuse3/cuse_lowlevel.h> 9 10 #include <linux/nvme_ioctl.h> 11 #include <linux/fs.h> 12 13 #include "nvme_internal.h" 14 #include "nvme_io_msg.h" 15 #include "nvme_cuse.h" 16 17 struct cuse_device { 18 char dev_name[128]; 19 uint32_t index; 20 int claim_fd; 21 char lock_name[64]; 22 23 struct spdk_nvme_ctrlr *ctrlr; /**< NVMe controller */ 24 uint32_t nsid; /**< NVMe name space id, or 0 */ 25 26 pthread_t tid; 27 struct fuse_session *session; 28 29 struct cuse_device *ctrlr_device; 30 TAILQ_HEAD(, cuse_device) ns_devices; 31 32 TAILQ_ENTRY(cuse_device) tailq; 33 }; 34 35 static pthread_mutex_t g_cuse_mtx = PTHREAD_MUTEX_INITIALIZER; 36 static TAILQ_HEAD(, cuse_device) g_ctrlr_ctx_head = TAILQ_HEAD_INITIALIZER(g_ctrlr_ctx_head); 37 static struct spdk_bit_array *g_ctrlr_started; 38 39 struct cuse_io_ctx { 40 struct spdk_nvme_cmd nvme_cmd; 41 enum spdk_nvme_data_transfer data_transfer; 42 43 uint64_t lba; 44 uint32_t lba_count; 45 uint16_t apptag; 46 uint16_t appmask; 47 48 void *data; 49 void *metadata; 50 51 int data_len; 52 int metadata_len; 53 54 fuse_req_t req; 55 }; 56 57 static void 58 cuse_io_ctx_free(struct cuse_io_ctx *ctx) 59 { 60 spdk_free(ctx->data); 61 spdk_free(ctx->metadata); 62 free(ctx); 63 } 64 65 #define FUSE_REPLY_CHECK_BUFFER(req, arg, out_bufsz, val) \ 66 if (out_bufsz == 0) { \ 67 struct iovec out_iov; \ 68 out_iov.iov_base = (void *)arg; \ 69 out_iov.iov_len = sizeof(val); \ 70 fuse_reply_ioctl_retry(req, NULL, 0, &out_iov, 1); \ 71 return; \ 72 } 73 74 #define FUSE_MAX_SIZE 128*1024 75 76 static bool 77 fuse_check_req_size(fuse_req_t req, struct iovec iov[], int iovcnt) 78 { 79 int total_iov_len = 0; 80 for (int i = 0; i < iovcnt; i++) { 81 total_iov_len += iov[i].iov_len; 82 if (total_iov_len > FUSE_MAX_SIZE) { 83 fuse_reply_err(req, ENOMEM); 84 SPDK_ERRLOG("FUSE request cannot be larger that %d\n", FUSE_MAX_SIZE); 85 return false; 86 } 87 } 88 return true; 89 } 90 91 static void 92 cuse_nvme_passthru_cmd_cb(void *arg, const struct spdk_nvme_cpl *cpl) 93 { 94 struct cuse_io_ctx *ctx = arg; 95 struct iovec out_iov[3]; 96 struct spdk_nvme_cpl _cpl; 97 int out_iovcnt = 0; 98 uint16_t status_field = cpl->status_raw >> 1; /* Drop out phase bit */ 99 100 memcpy(&_cpl, cpl, sizeof(struct spdk_nvme_cpl)); 101 out_iov[out_iovcnt].iov_base = &_cpl.cdw0; 102 out_iov[out_iovcnt].iov_len = sizeof(_cpl.cdw0); 103 out_iovcnt += 1; 104 105 if (ctx->data_transfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST) { 106 if (ctx->data_len > 0) { 107 out_iov[out_iovcnt].iov_base = ctx->data; 108 out_iov[out_iovcnt].iov_len = ctx->data_len; 109 out_iovcnt += 1; 110 } 111 if (ctx->metadata_len > 0) { 112 out_iov[out_iovcnt].iov_base = ctx->metadata; 113 out_iov[out_iovcnt].iov_len = ctx->metadata_len; 114 out_iovcnt += 1; 115 } 116 } 117 118 fuse_reply_ioctl_iov(ctx->req, status_field, out_iov, out_iovcnt); 119 cuse_io_ctx_free(ctx); 120 } 121 122 static void 123 cuse_nvme_passthru_cmd_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg) 124 { 125 int rc; 126 struct cuse_io_ctx *ctx = arg; 127 128 if (nsid != 0) { 129 rc = spdk_nvme_ctrlr_cmd_io_raw_with_md(ctrlr, ctrlr->external_io_msgs_qpair, &ctx->nvme_cmd, 130 ctx->data, 131 ctx->data_len, ctx->metadata, cuse_nvme_passthru_cmd_cb, (void *)ctx); 132 } else { 133 rc = spdk_nvme_ctrlr_cmd_admin_raw(ctrlr, &ctx->nvme_cmd, ctx->data, ctx->data_len, 134 cuse_nvme_passthru_cmd_cb, (void *)ctx); 135 } 136 if (rc < 0) { 137 fuse_reply_err(ctx->req, EINVAL); 138 cuse_io_ctx_free(ctx); 139 } 140 } 141 142 static void 143 cuse_nvme_passthru_cmd_send(fuse_req_t req, struct nvme_passthru_cmd *passthru_cmd, 144 const void *data, const void *metadata, int cmd) 145 { 146 struct cuse_io_ctx *ctx; 147 struct cuse_device *cuse_device = fuse_req_userdata(req); 148 int rv; 149 150 ctx = (struct cuse_io_ctx *)calloc(1, sizeof(struct cuse_io_ctx)); 151 if (!ctx) { 152 SPDK_ERRLOG("Cannot allocate memory for cuse_io_ctx\n"); 153 fuse_reply_err(req, ENOMEM); 154 return; 155 } 156 157 ctx->req = req; 158 ctx->data_transfer = spdk_nvme_opc_get_data_transfer(passthru_cmd->opcode); 159 160 memset(&ctx->nvme_cmd, 0, sizeof(ctx->nvme_cmd)); 161 ctx->nvme_cmd.opc = passthru_cmd->opcode; 162 ctx->nvme_cmd.nsid = passthru_cmd->nsid; 163 ctx->nvme_cmd.cdw10 = passthru_cmd->cdw10; 164 ctx->nvme_cmd.cdw11 = passthru_cmd->cdw11; 165 ctx->nvme_cmd.cdw12 = passthru_cmd->cdw12; 166 ctx->nvme_cmd.cdw13 = passthru_cmd->cdw13; 167 ctx->nvme_cmd.cdw14 = passthru_cmd->cdw14; 168 ctx->nvme_cmd.cdw15 = passthru_cmd->cdw15; 169 170 ctx->data_len = passthru_cmd->data_len; 171 ctx->metadata_len = passthru_cmd->metadata_len; 172 173 if (ctx->data_len > 0) { 174 ctx->data = spdk_malloc(ctx->data_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 175 if (!ctx->data) { 176 SPDK_ERRLOG("Cannot allocate memory for data\n"); 177 fuse_reply_err(req, ENOMEM); 178 free(ctx); 179 return; 180 } 181 if (data != NULL) { 182 memcpy(ctx->data, data, ctx->data_len); 183 } 184 } 185 186 if (ctx->metadata_len > 0) { 187 ctx->metadata = spdk_malloc(ctx->metadata_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 188 if (!ctx->metadata) { 189 SPDK_ERRLOG("Cannot allocate memory for metadata\n"); 190 fuse_reply_err(req, ENOMEM); 191 cuse_io_ctx_free(ctx); 192 return; 193 } 194 if (metadata != NULL) { 195 memcpy(ctx->metadata, metadata, ctx->metadata_len); 196 } 197 } 198 199 if ((unsigned int)cmd != NVME_IOCTL_ADMIN_CMD) { 200 /* Send NS for IO IOCTLs */ 201 rv = nvme_io_msg_send(cuse_device->ctrlr, passthru_cmd->nsid, cuse_nvme_passthru_cmd_execute, ctx); 202 } else { 203 /* NS == 0 for Admin IOCTLs */ 204 rv = nvme_io_msg_send(cuse_device->ctrlr, 0, cuse_nvme_passthru_cmd_execute, ctx); 205 } 206 if (rv) { 207 SPDK_ERRLOG("Cannot send io msg to the controller\n"); 208 fuse_reply_err(req, -rv); 209 cuse_io_ctx_free(ctx); 210 return; 211 } 212 } 213 214 static void 215 cuse_nvme_passthru_cmd(fuse_req_t req, int cmd, void *arg, 216 struct fuse_file_info *fi, unsigned flags, 217 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 218 { 219 struct nvme_passthru_cmd *passthru_cmd; 220 struct iovec in_iov[3], out_iov[3]; 221 int in_iovcnt = 0, out_iovcnt = 0; 222 const void *dptr = NULL, *mdptr = NULL; 223 enum spdk_nvme_data_transfer data_transfer; 224 225 in_iov[in_iovcnt].iov_base = (void *)arg; 226 in_iov[in_iovcnt].iov_len = sizeof(*passthru_cmd); 227 in_iovcnt += 1; 228 if (in_bufsz == 0) { 229 fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, NULL, out_iovcnt); 230 return; 231 } 232 233 passthru_cmd = (struct nvme_passthru_cmd *)in_buf; 234 data_transfer = spdk_nvme_opc_get_data_transfer(passthru_cmd->opcode); 235 236 if (data_transfer == SPDK_NVME_DATA_HOST_TO_CONTROLLER) { 237 /* Make data pointer accessible (RO) */ 238 if (passthru_cmd->addr != 0) { 239 in_iov[in_iovcnt].iov_base = (void *)passthru_cmd->addr; 240 in_iov[in_iovcnt].iov_len = passthru_cmd->data_len; 241 in_iovcnt += 1; 242 } 243 /* Make metadata pointer accessible (RO) */ 244 if (passthru_cmd->metadata != 0) { 245 in_iov[in_iovcnt].iov_base = (void *)passthru_cmd->metadata; 246 in_iov[in_iovcnt].iov_len = passthru_cmd->metadata_len; 247 in_iovcnt += 1; 248 } 249 } 250 251 if (!fuse_check_req_size(req, in_iov, in_iovcnt)) { 252 return; 253 } 254 /* Always make result field writeable regardless of data transfer bits */ 255 out_iov[out_iovcnt].iov_base = &((struct nvme_passthru_cmd *)arg)->result; 256 out_iov[out_iovcnt].iov_len = sizeof(uint32_t); 257 out_iovcnt += 1; 258 259 if (data_transfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST) { 260 /* Make data pointer accessible (WO) */ 261 if (passthru_cmd->data_len > 0) { 262 out_iov[out_iovcnt].iov_base = (void *)passthru_cmd->addr; 263 out_iov[out_iovcnt].iov_len = passthru_cmd->data_len; 264 out_iovcnt += 1; 265 } 266 /* Make metadata pointer accessible (WO) */ 267 if (passthru_cmd->metadata_len > 0) { 268 out_iov[out_iovcnt].iov_base = (void *)passthru_cmd->metadata; 269 out_iov[out_iovcnt].iov_len = passthru_cmd->metadata_len; 270 out_iovcnt += 1; 271 } 272 } 273 274 if (!fuse_check_req_size(req, out_iov, out_iovcnt)) { 275 return; 276 } 277 278 if (out_bufsz == 0) { 279 fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, out_iov, out_iovcnt); 280 return; 281 } 282 283 if (data_transfer == SPDK_NVME_DATA_BIDIRECTIONAL) { 284 fuse_reply_err(req, EINVAL); 285 return; 286 } 287 288 if (data_transfer == SPDK_NVME_DATA_HOST_TO_CONTROLLER) { 289 dptr = (passthru_cmd->addr == 0) ? NULL : in_buf + sizeof(*passthru_cmd); 290 mdptr = (passthru_cmd->metadata == 0) ? NULL : in_buf + sizeof(*passthru_cmd) + 291 passthru_cmd->data_len; 292 } 293 294 cuse_nvme_passthru_cmd_send(req, passthru_cmd, dptr, mdptr, cmd); 295 } 296 297 static void 298 cuse_nvme_reset_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg) 299 { 300 int rc; 301 fuse_req_t req = arg; 302 303 rc = spdk_nvme_ctrlr_reset(ctrlr); 304 if (rc) { 305 fuse_reply_err(req, rc); 306 return; 307 } 308 309 fuse_reply_ioctl_iov(req, 0, NULL, 0); 310 } 311 312 static void 313 cuse_nvme_subsys_reset_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg) 314 { 315 int rc; 316 fuse_req_t req = arg; 317 318 rc = spdk_nvme_ctrlr_reset_subsystem(ctrlr); 319 if (rc) { 320 fuse_reply_err(req, rc); 321 return; 322 } 323 324 fuse_reply_ioctl_iov(req, 0, NULL, 0); 325 } 326 327 static void 328 cuse_nvme_reset(fuse_req_t req, int cmd, void *arg, 329 struct fuse_file_info *fi, unsigned flags, 330 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 331 { 332 int rv; 333 struct cuse_device *cuse_device = fuse_req_userdata(req); 334 335 if (cuse_device->nsid) { 336 SPDK_ERRLOG("Namespace reset not supported\n"); 337 fuse_reply_err(req, EINVAL); 338 return; 339 } 340 341 if (cmd == NVME_IOCTL_SUBSYS_RESET) { 342 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_SUBSYS_RESET\n"); 343 rv = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_subsys_reset_execute, 344 (void *)req); 345 } else { 346 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_RESET\n"); 347 rv = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_reset_execute, (void *)req); 348 } 349 if (rv) { 350 SPDK_ERRLOG("Cannot send reset\n"); 351 fuse_reply_err(req, EINVAL); 352 } 353 } 354 355 static void 356 cuse_nvme_rescan_execute(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg) 357 { 358 fuse_req_t req = arg; 359 360 nvme_ctrlr_update_namespaces(ctrlr); 361 fuse_reply_ioctl_iov(req, 0, NULL, 0); 362 } 363 364 static void 365 cuse_nvme_rescan(fuse_req_t req, int cmd, void *arg, 366 struct fuse_file_info *fi, unsigned flags, 367 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 368 { 369 int rv; 370 struct cuse_device *cuse_device = fuse_req_userdata(req); 371 372 if (cuse_device->nsid) { 373 SPDK_ERRLOG("Namespace rescan not supported\n"); 374 fuse_reply_err(req, EINVAL); 375 return; 376 } 377 378 rv = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_rescan_execute, (void *)req); 379 if (rv) { 380 SPDK_ERRLOG("Cannot send rescan\n"); 381 fuse_reply_err(req, EINVAL); 382 } 383 } 384 385 /***************************************************************************** 386 * Namespace IO requests 387 */ 388 389 static void 390 cuse_nvme_submit_io_write_done(void *ref, const struct spdk_nvme_cpl *cpl) 391 { 392 struct cuse_io_ctx *ctx = (struct cuse_io_ctx *)ref; 393 uint16_t status_field = cpl->status_raw >> 1; /* Drop out phase bit */ 394 395 fuse_reply_ioctl_iov(ctx->req, status_field, NULL, 0); 396 397 cuse_io_ctx_free(ctx); 398 } 399 400 static void 401 cuse_nvme_submit_io_write_cb(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg) 402 { 403 int rc; 404 struct cuse_io_ctx *ctx = arg; 405 struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid); 406 407 rc = spdk_nvme_ns_cmd_write_with_md(ns, ctrlr->external_io_msgs_qpair, ctx->data, ctx->metadata, 408 ctx->lba, /* LBA start */ 409 ctx->lba_count, /* number of LBAs */ 410 cuse_nvme_submit_io_write_done, ctx, 0, 411 ctx->appmask, ctx->apptag); 412 413 if (rc != 0) { 414 SPDK_ERRLOG("write failed: rc = %d\n", rc); 415 fuse_reply_err(ctx->req, rc); 416 cuse_io_ctx_free(ctx); 417 return; 418 } 419 } 420 421 static void 422 cuse_nvme_submit_io_write(struct cuse_device *cuse_device, fuse_req_t req, int cmd, void *arg, 423 struct fuse_file_info *fi, unsigned flags, uint32_t block_size, uint32_t md_size, 424 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 425 { 426 const struct nvme_user_io *user_io = in_buf; 427 struct cuse_io_ctx *ctx; 428 int rc; 429 430 ctx = (struct cuse_io_ctx *)calloc(1, sizeof(struct cuse_io_ctx)); 431 if (!ctx) { 432 SPDK_ERRLOG("Cannot allocate memory for context\n"); 433 fuse_reply_err(req, ENOMEM); 434 return; 435 } 436 437 ctx->req = req; 438 ctx->lba = user_io->slba; 439 ctx->lba_count = user_io->nblocks + 1; 440 ctx->data_len = ctx->lba_count * block_size; 441 442 ctx->data = spdk_zmalloc(ctx->data_len, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY, 443 SPDK_MALLOC_DMA); 444 if (ctx->data == NULL) { 445 SPDK_ERRLOG("Write buffer allocation failed\n"); 446 fuse_reply_err(ctx->req, ENOMEM); 447 free(ctx); 448 return; 449 } 450 451 memcpy(ctx->data, in_buf + sizeof(*user_io), ctx->data_len); 452 453 if (user_io->metadata) { 454 ctx->apptag = user_io->apptag; 455 ctx->appmask = user_io->appmask; 456 ctx->metadata_len = md_size * ctx->lba_count; 457 ctx->metadata = spdk_zmalloc(ctx->metadata_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 458 459 if (ctx->metadata == NULL) { 460 SPDK_ERRLOG("Cannot allocate memory for metadata\n"); 461 if (ctx->metadata_len == 0) { 462 SPDK_ERRLOG("Device format does not support metadata\n"); 463 } 464 fuse_reply_err(req, ENOMEM); 465 cuse_io_ctx_free(ctx); 466 return; 467 } 468 469 memcpy(ctx->metadata, in_buf + sizeof(*user_io) + ctx->data_len, ctx->metadata_len); 470 } 471 472 rc = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_submit_io_write_cb, 473 ctx); 474 if (rc < 0) { 475 SPDK_ERRLOG("Cannot send write io\n"); 476 fuse_reply_err(ctx->req, rc); 477 cuse_io_ctx_free(ctx); 478 } 479 } 480 481 static void 482 cuse_nvme_submit_io_read_done(void *ref, const struct spdk_nvme_cpl *cpl) 483 { 484 struct cuse_io_ctx *ctx = (struct cuse_io_ctx *)ref; 485 struct iovec iov[2]; 486 int iovcnt = 0; 487 uint16_t status_field = cpl->status_raw >> 1; /* Drop out phase bit */ 488 489 iov[iovcnt].iov_base = ctx->data; 490 iov[iovcnt].iov_len = ctx->data_len; 491 iovcnt += 1; 492 493 if (ctx->metadata) { 494 iov[iovcnt].iov_base = ctx->metadata; 495 iov[iovcnt].iov_len = ctx->metadata_len; 496 iovcnt += 1; 497 } 498 499 fuse_reply_ioctl_iov(ctx->req, status_field, iov, iovcnt); 500 501 cuse_io_ctx_free(ctx); 502 } 503 504 static void 505 cuse_nvme_submit_io_read_cb(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg) 506 { 507 int rc; 508 struct cuse_io_ctx *ctx = arg; 509 struct spdk_nvme_ns *ns = spdk_nvme_ctrlr_get_ns(ctrlr, nsid); 510 511 rc = spdk_nvme_ns_cmd_read_with_md(ns, ctrlr->external_io_msgs_qpair, ctx->data, ctx->metadata, 512 ctx->lba, /* LBA start */ 513 ctx->lba_count, /* number of LBAs */ 514 cuse_nvme_submit_io_read_done, ctx, 0, 515 ctx->appmask, ctx->apptag); 516 517 if (rc != 0) { 518 SPDK_ERRLOG("read failed: rc = %d\n", rc); 519 fuse_reply_err(ctx->req, rc); 520 cuse_io_ctx_free(ctx); 521 return; 522 } 523 } 524 525 static void 526 cuse_nvme_submit_io_read(struct cuse_device *cuse_device, fuse_req_t req, int cmd, void *arg, 527 struct fuse_file_info *fi, unsigned flags, uint32_t block_size, uint32_t md_size, 528 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 529 { 530 int rc; 531 struct cuse_io_ctx *ctx; 532 const struct nvme_user_io *user_io = in_buf; 533 534 ctx = (struct cuse_io_ctx *)calloc(1, sizeof(struct cuse_io_ctx)); 535 if (!ctx) { 536 SPDK_ERRLOG("Cannot allocate memory for context\n"); 537 fuse_reply_err(req, ENOMEM); 538 return; 539 } 540 541 ctx->req = req; 542 ctx->lba = user_io->slba; 543 ctx->lba_count = user_io->nblocks + 1; 544 545 ctx->data_len = ctx->lba_count * block_size; 546 ctx->data = spdk_zmalloc(ctx->data_len, 0x1000, NULL, SPDK_ENV_SOCKET_ID_ANY, 547 SPDK_MALLOC_DMA); 548 if (ctx->data == NULL) { 549 SPDK_ERRLOG("Read buffer allocation failed\n"); 550 fuse_reply_err(ctx->req, ENOMEM); 551 free(ctx); 552 return; 553 } 554 555 if (user_io->metadata) { 556 ctx->apptag = user_io->apptag; 557 ctx->appmask = user_io->appmask; 558 ctx->metadata_len = md_size * ctx->lba_count; 559 ctx->metadata = spdk_zmalloc(ctx->metadata_len, 4096, NULL, SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA); 560 561 if (ctx->metadata == NULL) { 562 SPDK_ERRLOG("Cannot allocate memory for metadata\n"); 563 if (ctx->metadata_len == 0) { 564 SPDK_ERRLOG("Device format does not support metadata\n"); 565 } 566 fuse_reply_err(req, ENOMEM); 567 cuse_io_ctx_free(ctx); 568 return; 569 } 570 } 571 572 rc = nvme_io_msg_send(cuse_device->ctrlr, cuse_device->nsid, cuse_nvme_submit_io_read_cb, ctx); 573 if (rc < 0) { 574 SPDK_ERRLOG("Cannot send read io\n"); 575 fuse_reply_err(ctx->req, rc); 576 cuse_io_ctx_free(ctx); 577 } 578 } 579 580 581 static void 582 cuse_nvme_submit_io(fuse_req_t req, int cmd, void *arg, 583 struct fuse_file_info *fi, unsigned flags, 584 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 585 { 586 const struct nvme_user_io *user_io; 587 struct iovec in_iov[3], out_iov[2]; 588 int in_iovcnt = 0, out_iovcnt = 0; 589 struct cuse_device *cuse_device = fuse_req_userdata(req); 590 struct spdk_nvme_ns *ns; 591 uint32_t block_size; 592 uint32_t md_size; 593 594 in_iov[in_iovcnt].iov_base = (void *)arg; 595 in_iov[in_iovcnt].iov_len = sizeof(*user_io); 596 in_iovcnt += 1; 597 if (in_bufsz == 0) { 598 fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, NULL, 0); 599 return; 600 } 601 602 user_io = in_buf; 603 604 ns = spdk_nvme_ctrlr_get_ns(cuse_device->ctrlr, cuse_device->nsid); 605 block_size = spdk_nvme_ns_get_sector_size(ns); 606 md_size = spdk_nvme_ns_get_md_size(ns); 607 608 switch (user_io->opcode) { 609 case SPDK_NVME_OPC_READ: 610 out_iov[out_iovcnt].iov_base = (void *)user_io->addr; 611 out_iov[out_iovcnt].iov_len = (user_io->nblocks + 1) * block_size; 612 out_iovcnt += 1; 613 if (user_io->metadata != 0) { 614 out_iov[out_iovcnt].iov_base = (void *)user_io->metadata; 615 out_iov[out_iovcnt].iov_len = (user_io->nblocks + 1) * md_size; 616 out_iovcnt += 1; 617 } 618 if (!fuse_check_req_size(req, out_iov, out_iovcnt)) { 619 return; 620 } 621 if (out_bufsz == 0) { 622 fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, out_iov, out_iovcnt); 623 return; 624 } 625 626 cuse_nvme_submit_io_read(cuse_device, req, cmd, arg, fi, flags, 627 block_size, md_size, in_buf, in_bufsz, out_bufsz); 628 break; 629 case SPDK_NVME_OPC_WRITE: 630 in_iov[in_iovcnt].iov_base = (void *)user_io->addr; 631 in_iov[in_iovcnt].iov_len = (user_io->nblocks + 1) * block_size; 632 in_iovcnt += 1; 633 if (user_io->metadata != 0) { 634 in_iov[in_iovcnt].iov_base = (void *)user_io->metadata; 635 in_iov[in_iovcnt].iov_len = (user_io->nblocks + 1) * md_size; 636 in_iovcnt += 1; 637 } 638 if (!fuse_check_req_size(req, in_iov, in_iovcnt)) { 639 return; 640 } 641 if (in_bufsz == sizeof(*user_io)) { 642 fuse_reply_ioctl_retry(req, in_iov, in_iovcnt, NULL, out_iovcnt); 643 return; 644 } 645 646 cuse_nvme_submit_io_write(cuse_device, req, cmd, arg, fi, flags, 647 block_size, md_size, in_buf, in_bufsz, out_bufsz); 648 break; 649 default: 650 SPDK_ERRLOG("SUBMIT_IO: opc:%d not valid\n", user_io->opcode); 651 fuse_reply_err(req, EINVAL); 652 return; 653 } 654 655 } 656 657 /***************************************************************************** 658 * Other namespace IOCTLs 659 */ 660 static void 661 cuse_blkgetsize64(fuse_req_t req, int cmd, void *arg, 662 struct fuse_file_info *fi, unsigned flags, 663 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 664 { 665 uint64_t size; 666 struct spdk_nvme_ns *ns; 667 struct cuse_device *cuse_device = fuse_req_userdata(req); 668 669 FUSE_REPLY_CHECK_BUFFER(req, arg, out_bufsz, size); 670 671 ns = spdk_nvme_ctrlr_get_ns(cuse_device->ctrlr, cuse_device->nsid); 672 size = spdk_nvme_ns_get_num_sectors(ns); 673 fuse_reply_ioctl(req, 0, &size, sizeof(size)); 674 } 675 676 static void 677 cuse_blkpbszget(fuse_req_t req, int cmd, void *arg, 678 struct fuse_file_info *fi, unsigned flags, 679 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 680 { 681 int pbsz; 682 struct spdk_nvme_ns *ns; 683 struct cuse_device *cuse_device = fuse_req_userdata(req); 684 685 FUSE_REPLY_CHECK_BUFFER(req, arg, out_bufsz, pbsz); 686 687 ns = spdk_nvme_ctrlr_get_ns(cuse_device->ctrlr, cuse_device->nsid); 688 pbsz = spdk_nvme_ns_get_sector_size(ns); 689 fuse_reply_ioctl(req, 0, &pbsz, sizeof(pbsz)); 690 } 691 692 static void 693 cuse_blkgetsize(fuse_req_t req, int cmd, void *arg, 694 struct fuse_file_info *fi, unsigned flags, 695 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 696 { 697 long size; 698 struct spdk_nvme_ns *ns; 699 struct cuse_device *cuse_device = fuse_req_userdata(req); 700 701 FUSE_REPLY_CHECK_BUFFER(req, arg, out_bufsz, size); 702 703 ns = spdk_nvme_ctrlr_get_ns(cuse_device->ctrlr, cuse_device->nsid); 704 705 /* return size in 512 bytes blocks */ 706 size = spdk_nvme_ns_get_num_sectors(ns) * 512 / spdk_nvme_ns_get_sector_size(ns); 707 fuse_reply_ioctl(req, 0, &size, sizeof(size)); 708 } 709 710 static void 711 cuse_blkgetsectorsize(fuse_req_t req, int cmd, void *arg, 712 struct fuse_file_info *fi, unsigned flags, 713 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 714 { 715 int ssize; 716 struct spdk_nvme_ns *ns; 717 struct cuse_device *cuse_device = fuse_req_userdata(req); 718 719 FUSE_REPLY_CHECK_BUFFER(req, arg, out_bufsz, ssize); 720 721 ns = spdk_nvme_ctrlr_get_ns(cuse_device->ctrlr, cuse_device->nsid); 722 ssize = spdk_nvme_ns_get_sector_size(ns); 723 fuse_reply_ioctl(req, 0, &ssize, sizeof(ssize)); 724 } 725 726 static void 727 cuse_getid(fuse_req_t req, int cmd, void *arg, 728 struct fuse_file_info *fi, unsigned flags, 729 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 730 { 731 struct cuse_device *cuse_device = fuse_req_userdata(req); 732 733 fuse_reply_ioctl(req, cuse_device->nsid, NULL, 0); 734 } 735 736 static void 737 cuse_ctrlr_ioctl(fuse_req_t req, int cmd, void *arg, 738 struct fuse_file_info *fi, unsigned flags, 739 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 740 { 741 if (flags & FUSE_IOCTL_COMPAT) { 742 fuse_reply_err(req, ENOSYS); 743 return; 744 } 745 746 switch ((unsigned int)cmd) { 747 case NVME_IOCTL_ADMIN_CMD: 748 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_ADMIN_CMD\n"); 749 cuse_nvme_passthru_cmd(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 750 break; 751 752 case NVME_IOCTL_RESET: 753 case NVME_IOCTL_SUBSYS_RESET: 754 cuse_nvme_reset(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 755 break; 756 757 case NVME_IOCTL_RESCAN: 758 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_RESCAN\n"); 759 cuse_nvme_rescan(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 760 break; 761 762 default: 763 SPDK_ERRLOG("Unsupported IOCTL 0x%X.\n", cmd); 764 fuse_reply_err(req, ENOTTY); 765 } 766 } 767 768 static void 769 cuse_ns_ioctl(fuse_req_t req, int cmd, void *arg, 770 struct fuse_file_info *fi, unsigned flags, 771 const void *in_buf, size_t in_bufsz, size_t out_bufsz) 772 { 773 if (flags & FUSE_IOCTL_COMPAT) { 774 fuse_reply_err(req, ENOSYS); 775 return; 776 } 777 778 switch ((unsigned int)cmd) { 779 case NVME_IOCTL_ADMIN_CMD: 780 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_ADMIN_CMD\n"); 781 cuse_nvme_passthru_cmd(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 782 break; 783 784 case NVME_IOCTL_SUBMIT_IO: 785 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_SUBMIT_IO\n"); 786 cuse_nvme_submit_io(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 787 break; 788 789 case NVME_IOCTL_IO_CMD: 790 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_IO_CMD\n"); 791 cuse_nvme_passthru_cmd(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 792 break; 793 794 case NVME_IOCTL_ID: 795 SPDK_DEBUGLOG(nvme_cuse, "NVME_IOCTL_ID\n"); 796 cuse_getid(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 797 break; 798 799 case BLKPBSZGET: 800 SPDK_DEBUGLOG(nvme_cuse, "BLKPBSZGET\n"); 801 cuse_blkpbszget(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 802 break; 803 804 case BLKSSZGET: 805 SPDK_DEBUGLOG(nvme_cuse, "BLKSSZGET\n"); 806 cuse_blkgetsectorsize(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 807 break; 808 809 case BLKGETSIZE: 810 SPDK_DEBUGLOG(nvme_cuse, "BLKGETSIZE\n"); 811 /* Returns the device size as a number of 512-byte blocks (returns pointer to long) */ 812 cuse_blkgetsize(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 813 break; 814 815 case BLKGETSIZE64: 816 SPDK_DEBUGLOG(nvme_cuse, "BLKGETSIZE64\n"); 817 /* Returns the device size in sectors (returns pointer to uint64_t) */ 818 cuse_blkgetsize64(req, cmd, arg, fi, flags, in_buf, in_bufsz, out_bufsz); 819 break; 820 821 default: 822 SPDK_ERRLOG("Unsupported IOCTL 0x%X.\n", cmd); 823 fuse_reply_err(req, ENOTTY); 824 } 825 } 826 827 /***************************************************************************** 828 * CUSE threads initialization. 829 */ 830 831 static void 832 cuse_open(fuse_req_t req, struct fuse_file_info *fi) 833 { 834 fuse_reply_open(req, fi); 835 } 836 837 static const struct cuse_lowlevel_ops cuse_ctrlr_clop = { 838 .open = cuse_open, 839 .ioctl = cuse_ctrlr_ioctl, 840 }; 841 842 static const struct cuse_lowlevel_ops cuse_ns_clop = { 843 .open = cuse_open, 844 .ioctl = cuse_ns_ioctl, 845 }; 846 847 static int 848 cuse_session_create(struct cuse_device *cuse_device) 849 { 850 char *cuse_argv[] = { "cuse", "-f" }; 851 int multithreaded; 852 int cuse_argc = SPDK_COUNTOF(cuse_argv); 853 struct cuse_info ci; 854 char devname_arg[128 + 8]; 855 const char *dev_info_argv[] = { devname_arg }; 856 857 snprintf(devname_arg, sizeof(devname_arg), "DEVNAME=%s", cuse_device->dev_name); 858 859 memset(&ci, 0, sizeof(ci)); 860 ci.dev_info_argc = 1; 861 ci.dev_info_argv = dev_info_argv; 862 ci.flags = CUSE_UNRESTRICTED_IOCTL; 863 864 if (cuse_device->nsid) { 865 cuse_device->session = cuse_lowlevel_setup(cuse_argc, cuse_argv, &ci, &cuse_ns_clop, 866 &multithreaded, cuse_device); 867 } else { 868 cuse_device->session = cuse_lowlevel_setup(cuse_argc, cuse_argv, &ci, &cuse_ctrlr_clop, 869 &multithreaded, cuse_device); 870 } 871 872 if (!cuse_device->session) { 873 SPDK_ERRLOG("Cannot create cuse session\n"); 874 return -1; 875 } 876 SPDK_NOTICELOG("fuse session for device %s created\n", cuse_device->dev_name); 877 return 0; 878 } 879 880 static void * 881 cuse_thread(void *arg) 882 { 883 struct cuse_device *cuse_device = arg; 884 int rc; 885 struct fuse_buf buf = { .mem = NULL }; 886 struct pollfd fds; 887 int timeout_msecs = 500; 888 889 spdk_unaffinitize_thread(); 890 891 /* Receive and process fuse requests */ 892 fds.fd = fuse_session_fd(cuse_device->session); 893 fds.events = POLLIN; 894 while (!fuse_session_exited(cuse_device->session)) { 895 rc = poll(&fds, 1, timeout_msecs); 896 if (rc <= 0) { 897 continue; 898 } 899 rc = fuse_session_receive_buf(cuse_device->session, &buf); 900 if (rc > 0) { 901 fuse_session_process_buf(cuse_device->session, &buf); 902 } 903 } 904 free(buf.mem); 905 fuse_session_reset(cuse_device->session); 906 pthread_exit(NULL); 907 } 908 909 static struct cuse_device *nvme_cuse_get_cuse_ns_device(struct spdk_nvme_ctrlr *ctrlr, 910 uint32_t nsid); 911 912 /***************************************************************************** 913 * CUSE devices management 914 */ 915 916 static int 917 cuse_nvme_ns_start(struct cuse_device *ctrlr_device, uint32_t nsid) 918 { 919 struct cuse_device *ns_device; 920 int rv; 921 922 ns_device = nvme_cuse_get_cuse_ns_device(ctrlr_device->ctrlr, nsid); 923 if (ns_device != NULL) { 924 return 0; 925 } 926 927 ns_device = calloc(1, sizeof(struct cuse_device)); 928 if (ns_device == NULL) { 929 return -ENOMEM; 930 } 931 932 ns_device->ctrlr = ctrlr_device->ctrlr; 933 ns_device->ctrlr_device = ctrlr_device; 934 ns_device->nsid = nsid; 935 rv = snprintf(ns_device->dev_name, sizeof(ns_device->dev_name), "%sn%d", 936 ctrlr_device->dev_name, ns_device->nsid); 937 if (rv < 0) { 938 SPDK_ERRLOG("Device name too long.\n"); 939 free(ns_device); 940 return -ENAMETOOLONG; 941 } 942 rv = cuse_session_create(ns_device); 943 if (rv != 0) { 944 free(ns_device); 945 return rv; 946 } 947 rv = pthread_create(&ns_device->tid, NULL, cuse_thread, ns_device); 948 if (rv != 0) { 949 SPDK_ERRLOG("pthread_create failed\n"); 950 free(ns_device); 951 return -rv; 952 } 953 TAILQ_INSERT_TAIL(&ctrlr_device->ns_devices, ns_device, tailq); 954 955 return 0; 956 } 957 958 static void 959 cuse_nvme_ns_stop(struct cuse_device *ctrlr_device, struct cuse_device *ns_device) 960 { 961 if (ns_device->session != NULL) { 962 fuse_session_exit(ns_device->session); 963 } 964 pthread_join(ns_device->tid, NULL); 965 TAILQ_REMOVE(&ctrlr_device->ns_devices, ns_device, tailq); 966 if (ns_device->session != NULL) { 967 cuse_lowlevel_teardown(ns_device->session); 968 } 969 free(ns_device); 970 } 971 972 static int 973 nvme_cuse_claim(struct cuse_device *ctrlr_device, uint32_t index) 974 { 975 int dev_fd; 976 int pid; 977 void *dev_map; 978 struct flock cusedev_lock = { 979 .l_type = F_WRLCK, 980 .l_whence = SEEK_SET, 981 .l_start = 0, 982 .l_len = 0, 983 }; 984 985 snprintf(ctrlr_device->lock_name, sizeof(ctrlr_device->lock_name), 986 "/var/tmp/spdk_nvme_cuse_lock_%" PRIu32, index); 987 988 dev_fd = open(ctrlr_device->lock_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 989 if (dev_fd == -1) { 990 SPDK_ERRLOG("could not open %s\n", ctrlr_device->lock_name); 991 return -errno; 992 } 993 994 if (ftruncate(dev_fd, sizeof(int)) != 0) { 995 SPDK_ERRLOG("could not truncate %s\n", ctrlr_device->lock_name); 996 close(dev_fd); 997 return -errno; 998 } 999 1000 dev_map = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, 1001 MAP_SHARED, dev_fd, 0); 1002 if (dev_map == MAP_FAILED) { 1003 SPDK_ERRLOG("could not mmap dev %s (%d)\n", ctrlr_device->lock_name, errno); 1004 close(dev_fd); 1005 return -errno; 1006 } 1007 1008 if (fcntl(dev_fd, F_SETLK, &cusedev_lock) != 0) { 1009 pid = *(int *)dev_map; 1010 SPDK_ERRLOG("Cannot create lock on device %s, probably" 1011 " process %d has claimed it\n", ctrlr_device->lock_name, pid); 1012 munmap(dev_map, sizeof(int)); 1013 close(dev_fd); 1014 /* F_SETLK returns unspecified errnos, normalize them */ 1015 return -EACCES; 1016 } 1017 1018 *(int *)dev_map = (int)getpid(); 1019 munmap(dev_map, sizeof(int)); 1020 ctrlr_device->claim_fd = dev_fd; 1021 ctrlr_device->index = index; 1022 /* Keep dev_fd open to maintain the lock. */ 1023 return 0; 1024 } 1025 1026 static void 1027 nvme_cuse_unclaim(struct cuse_device *ctrlr_device) 1028 { 1029 close(ctrlr_device->claim_fd); 1030 ctrlr_device->claim_fd = -1; 1031 unlink(ctrlr_device->lock_name); 1032 } 1033 1034 static void 1035 cuse_nvme_ctrlr_stop(struct cuse_device *ctrlr_device) 1036 { 1037 struct cuse_device *ns_device, *tmp; 1038 1039 TAILQ_FOREACH_SAFE(ns_device, &ctrlr_device->ns_devices, tailq, tmp) { 1040 cuse_nvme_ns_stop(ctrlr_device, ns_device); 1041 } 1042 1043 assert(TAILQ_EMPTY(&ctrlr_device->ns_devices)); 1044 1045 fuse_session_exit(ctrlr_device->session); 1046 pthread_join(ctrlr_device->tid, NULL); 1047 TAILQ_REMOVE(&g_ctrlr_ctx_head, ctrlr_device, tailq); 1048 spdk_bit_array_clear(g_ctrlr_started, ctrlr_device->index); 1049 if (spdk_bit_array_count_set(g_ctrlr_started) == 0) { 1050 spdk_bit_array_free(&g_ctrlr_started); 1051 } 1052 nvme_cuse_unclaim(ctrlr_device); 1053 if (ctrlr_device->session != NULL) { 1054 cuse_lowlevel_teardown(ctrlr_device->session); 1055 } 1056 free(ctrlr_device); 1057 } 1058 1059 static int 1060 cuse_nvme_ctrlr_update_namespaces(struct cuse_device *ctrlr_device) 1061 { 1062 struct cuse_device *ns_device, *tmp; 1063 uint32_t nsid; 1064 1065 /* Remove namespaces that have disappeared */ 1066 TAILQ_FOREACH_SAFE(ns_device, &ctrlr_device->ns_devices, tailq, tmp) { 1067 if (!spdk_nvme_ctrlr_is_active_ns(ctrlr_device->ctrlr, ns_device->nsid)) { 1068 cuse_nvme_ns_stop(ctrlr_device, ns_device); 1069 } 1070 } 1071 1072 /* Add new namespaces */ 1073 nsid = spdk_nvme_ctrlr_get_first_active_ns(ctrlr_device->ctrlr); 1074 while (nsid != 0) { 1075 if (cuse_nvme_ns_start(ctrlr_device, nsid) < 0) { 1076 SPDK_ERRLOG("Cannot start CUSE namespace device."); 1077 return -1; 1078 } 1079 1080 nsid = spdk_nvme_ctrlr_get_next_active_ns(ctrlr_device->ctrlr, nsid); 1081 } 1082 1083 return 0; 1084 } 1085 1086 static int 1087 nvme_cuse_start(struct spdk_nvme_ctrlr *ctrlr) 1088 { 1089 int rv = 0; 1090 struct cuse_device *ctrlr_device; 1091 1092 SPDK_NOTICELOG("Creating cuse device for controller\n"); 1093 1094 if (g_ctrlr_started == NULL) { 1095 g_ctrlr_started = spdk_bit_array_create(128); 1096 if (g_ctrlr_started == NULL) { 1097 SPDK_ERRLOG("Cannot create bit array\n"); 1098 return -ENOMEM; 1099 } 1100 } 1101 1102 ctrlr_device = (struct cuse_device *)calloc(1, sizeof(struct cuse_device)); 1103 if (!ctrlr_device) { 1104 SPDK_ERRLOG("Cannot allocate memory for ctrlr_device."); 1105 rv = -ENOMEM; 1106 goto free_device; 1107 } 1108 1109 ctrlr_device->ctrlr = ctrlr; 1110 1111 /* Check if device already exists, if not increment index until success */ 1112 ctrlr_device->index = 0; 1113 while (1) { 1114 ctrlr_device->index = spdk_bit_array_find_first_clear(g_ctrlr_started, ctrlr_device->index); 1115 if (ctrlr_device->index == UINT32_MAX) { 1116 SPDK_ERRLOG("Too many registered controllers\n"); 1117 goto free_device; 1118 } 1119 1120 if (nvme_cuse_claim(ctrlr_device, ctrlr_device->index) == 0) { 1121 break; 1122 } 1123 ctrlr_device->index++; 1124 } 1125 spdk_bit_array_set(g_ctrlr_started, ctrlr_device->index); 1126 snprintf(ctrlr_device->dev_name, sizeof(ctrlr_device->dev_name), "spdk/nvme%d", 1127 ctrlr_device->index); 1128 1129 rv = cuse_session_create(ctrlr_device); 1130 if (rv != 0) { 1131 goto clear_and_free; 1132 } 1133 1134 rv = pthread_create(&ctrlr_device->tid, NULL, cuse_thread, ctrlr_device); 1135 if (rv != 0) { 1136 SPDK_ERRLOG("pthread_create failed\n"); 1137 rv = -rv; 1138 goto clear_and_free; 1139 } 1140 1141 TAILQ_INSERT_TAIL(&g_ctrlr_ctx_head, ctrlr_device, tailq); 1142 1143 TAILQ_INIT(&ctrlr_device->ns_devices); 1144 1145 /* Start all active namespaces */ 1146 if (cuse_nvme_ctrlr_update_namespaces(ctrlr_device) < 0) { 1147 SPDK_ERRLOG("Cannot start CUSE namespace devices."); 1148 cuse_nvme_ctrlr_stop(ctrlr_device); 1149 rv = -1; 1150 goto clear_and_free; 1151 } 1152 1153 return 0; 1154 1155 clear_and_free: 1156 spdk_bit_array_clear(g_ctrlr_started, ctrlr_device->index); 1157 free_device: 1158 free(ctrlr_device); 1159 if (spdk_bit_array_count_set(g_ctrlr_started) == 0) { 1160 spdk_bit_array_free(&g_ctrlr_started); 1161 } 1162 return rv; 1163 } 1164 1165 static struct cuse_device * 1166 nvme_cuse_get_cuse_ctrlr_device(struct spdk_nvme_ctrlr *ctrlr) 1167 { 1168 struct cuse_device *ctrlr_device = NULL; 1169 1170 TAILQ_FOREACH(ctrlr_device, &g_ctrlr_ctx_head, tailq) { 1171 if (ctrlr_device->ctrlr == ctrlr) { 1172 break; 1173 } 1174 } 1175 1176 return ctrlr_device; 1177 } 1178 1179 static struct cuse_device * 1180 nvme_cuse_get_cuse_ns_device(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid) 1181 { 1182 struct cuse_device *ctrlr_device = NULL; 1183 struct cuse_device *ns_device; 1184 1185 ctrlr_device = nvme_cuse_get_cuse_ctrlr_device(ctrlr); 1186 if (!ctrlr_device) { 1187 return NULL; 1188 } 1189 1190 TAILQ_FOREACH(ns_device, &ctrlr_device->ns_devices, tailq) { 1191 if (ns_device->nsid == nsid) { 1192 return ns_device; 1193 } 1194 } 1195 1196 return NULL; 1197 } 1198 1199 static void 1200 nvme_cuse_stop(struct spdk_nvme_ctrlr *ctrlr) 1201 { 1202 struct cuse_device *ctrlr_device; 1203 1204 pthread_mutex_lock(&g_cuse_mtx); 1205 1206 ctrlr_device = nvme_cuse_get_cuse_ctrlr_device(ctrlr); 1207 if (!ctrlr_device) { 1208 SPDK_ERRLOG("Cannot find associated CUSE device\n"); 1209 pthread_mutex_unlock(&g_cuse_mtx); 1210 return; 1211 } 1212 1213 cuse_nvme_ctrlr_stop(ctrlr_device); 1214 1215 pthread_mutex_unlock(&g_cuse_mtx); 1216 } 1217 1218 static void 1219 nvme_cuse_update(struct spdk_nvme_ctrlr *ctrlr) 1220 { 1221 struct cuse_device *ctrlr_device; 1222 1223 pthread_mutex_lock(&g_cuse_mtx); 1224 1225 ctrlr_device = nvme_cuse_get_cuse_ctrlr_device(ctrlr); 1226 if (!ctrlr_device) { 1227 pthread_mutex_unlock(&g_cuse_mtx); 1228 return; 1229 } 1230 1231 cuse_nvme_ctrlr_update_namespaces(ctrlr_device); 1232 1233 pthread_mutex_unlock(&g_cuse_mtx); 1234 } 1235 1236 static struct nvme_io_msg_producer cuse_nvme_io_msg_producer = { 1237 .name = "cuse", 1238 .stop = nvme_cuse_stop, 1239 .update = nvme_cuse_update, 1240 }; 1241 1242 int 1243 spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr) 1244 { 1245 int rc; 1246 1247 rc = nvme_io_msg_ctrlr_register(ctrlr, &cuse_nvme_io_msg_producer); 1248 if (rc) { 1249 return rc; 1250 } 1251 1252 pthread_mutex_lock(&g_cuse_mtx); 1253 1254 rc = nvme_cuse_start(ctrlr); 1255 if (rc) { 1256 nvme_io_msg_ctrlr_unregister(ctrlr, &cuse_nvme_io_msg_producer); 1257 } 1258 1259 pthread_mutex_unlock(&g_cuse_mtx); 1260 1261 return rc; 1262 } 1263 1264 int 1265 spdk_nvme_cuse_unregister(struct spdk_nvme_ctrlr *ctrlr) 1266 { 1267 struct cuse_device *ctrlr_device; 1268 1269 pthread_mutex_lock(&g_cuse_mtx); 1270 1271 ctrlr_device = nvme_cuse_get_cuse_ctrlr_device(ctrlr); 1272 if (!ctrlr_device) { 1273 SPDK_ERRLOG("Cannot find associated CUSE device\n"); 1274 pthread_mutex_unlock(&g_cuse_mtx); 1275 return -ENODEV; 1276 } 1277 1278 cuse_nvme_ctrlr_stop(ctrlr_device); 1279 1280 pthread_mutex_unlock(&g_cuse_mtx); 1281 1282 nvme_io_msg_ctrlr_unregister(ctrlr, &cuse_nvme_io_msg_producer); 1283 1284 return 0; 1285 } 1286 1287 void 1288 spdk_nvme_cuse_update_namespaces(struct spdk_nvme_ctrlr *ctrlr) 1289 { 1290 nvme_cuse_update(ctrlr); 1291 } 1292 1293 int 1294 spdk_nvme_cuse_get_ctrlr_name(struct spdk_nvme_ctrlr *ctrlr, char *name, size_t *size) 1295 { 1296 struct cuse_device *ctrlr_device; 1297 size_t req_len; 1298 1299 pthread_mutex_lock(&g_cuse_mtx); 1300 1301 ctrlr_device = nvme_cuse_get_cuse_ctrlr_device(ctrlr); 1302 if (!ctrlr_device) { 1303 pthread_mutex_unlock(&g_cuse_mtx); 1304 return -ENODEV; 1305 } 1306 1307 req_len = strnlen(ctrlr_device->dev_name, sizeof(ctrlr_device->dev_name)); 1308 if (*size < req_len) { 1309 *size = req_len; 1310 pthread_mutex_unlock(&g_cuse_mtx); 1311 return -ENOSPC; 1312 } 1313 snprintf(name, req_len + 1, "%s", ctrlr_device->dev_name); 1314 1315 pthread_mutex_unlock(&g_cuse_mtx); 1316 1317 return 0; 1318 } 1319 1320 int 1321 spdk_nvme_cuse_get_ns_name(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, char *name, size_t *size) 1322 { 1323 struct cuse_device *ns_device; 1324 size_t req_len; 1325 1326 pthread_mutex_lock(&g_cuse_mtx); 1327 1328 ns_device = nvme_cuse_get_cuse_ns_device(ctrlr, nsid); 1329 if (!ns_device) { 1330 pthread_mutex_unlock(&g_cuse_mtx); 1331 return -ENODEV; 1332 } 1333 1334 req_len = strnlen(ns_device->dev_name, sizeof(ns_device->dev_name)); 1335 if (*size < req_len) { 1336 *size = req_len; 1337 pthread_mutex_unlock(&g_cuse_mtx); 1338 return -ENOSPC; 1339 } 1340 snprintf(name, req_len + 1, "%s", ns_device->dev_name); 1341 1342 pthread_mutex_unlock(&g_cuse_mtx); 1343 1344 return 0; 1345 } 1346 1347 SPDK_LOG_REGISTER_COMPONENT(nvme_cuse) 1348