1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 * Copyright (c) croit GmbH. 5 * All rights reserved. 6 */ 7 8 #include <sys/queue.h> 9 10 #include "spdk/bdev.h" 11 #include "spdk/bdev_module.h" 12 #include "spdk/endian.h" 13 #include "spdk/env.h" 14 #include "spdk/json.h" 15 #include "spdk/thread.h" 16 #include "spdk/queue.h" 17 #include "spdk/string.h" 18 #include "spdk/stdinc.h" 19 #include "spdk/log.h" 20 21 #include <daos.h> 22 #include <daos_event.h> 23 #include <daos_fs.h> 24 #include <daos_types.h> 25 #include <daos_pool.h> 26 #include <daos_cont.h> 27 #include <daos_errno.h> 28 29 #include "bdev_daos.h" 30 31 #define BDEV_DAOS_IOVECS_MAX 32 32 33 struct bdev_daos_task { 34 daos_event_t ev; 35 struct spdk_thread *submit_td; 36 struct spdk_bdev_io *bdev_io; 37 38 enum spdk_bdev_io_status status; 39 40 uint64_t offset; 41 42 /* DAOS version of iovec and scatter/gather */ 43 daos_size_t read_size; 44 d_iov_t diovs[BDEV_DAOS_IOVECS_MAX]; 45 d_sg_list_t sgl; 46 }; 47 48 struct bdev_daos { 49 struct spdk_bdev disk; 50 51 char pool_name[DAOS_PROP_MAX_LABEL_BUF_LEN]; 52 char cont_name[DAOS_PROP_MAX_LABEL_BUF_LEN]; 53 54 struct bdev_daos_task *reset_task; 55 struct spdk_poller *reset_retry_timer; 56 }; 57 58 struct bdev_daos_io_channel { 59 struct bdev_daos *disk; 60 struct spdk_poller *poller; 61 62 daos_handle_t pool; 63 daos_handle_t cont; 64 65 dfs_t *dfs; 66 dfs_obj_t *obj; 67 daos_handle_t queue; 68 }; 69 70 static uint32_t g_bdev_daos_init_count = 0; 71 static pthread_mutex_t g_bdev_daos_init_mutex = PTHREAD_MUTEX_INITIALIZER; 72 73 static int bdev_daos_initialize(void); 74 75 static int bdev_get_daos_engine(void); 76 static int bdev_daos_put_engine(void); 77 78 static int 79 bdev_daos_get_ctx_size(void) 80 { 81 return sizeof(struct bdev_daos_task); 82 } 83 84 static struct spdk_bdev_module daos_if = { 85 .name = "daos", 86 .module_init = bdev_daos_initialize, 87 .get_ctx_size = bdev_daos_get_ctx_size, 88 }; 89 90 SPDK_BDEV_MODULE_REGISTER(daos, &daos_if) 91 92 static void 93 bdev_daos_free(struct bdev_daos *bdev_daos) 94 { 95 if (!bdev_daos) { 96 return; 97 } 98 99 free(bdev_daos->disk.name); 100 free(bdev_daos); 101 } 102 103 static void 104 bdev_daos_destruct_cb(void *io_device) 105 { 106 int rc; 107 struct bdev_daos *daos = io_device; 108 109 assert(daos != NULL); 110 111 bdev_daos_free(daos); 112 113 rc = bdev_daos_put_engine(); 114 if (rc) { 115 SPDK_ERRLOG("could not de-initialize DAOS engine: " DF_RC "\n", DP_RC(rc)); 116 } 117 } 118 119 static int 120 bdev_daos_destruct(void *ctx) 121 { 122 struct bdev_daos *daos = ctx; 123 124 SPDK_NOTICELOG("%s: destroying bdev_daos device\n", daos->disk.name); 125 126 spdk_io_device_unregister(daos, bdev_daos_destruct_cb); 127 128 return 0; 129 } 130 131 static void 132 _bdev_daos_io_complete(void *bdev_daos_task) 133 { 134 struct bdev_daos_task *task = bdev_daos_task; 135 136 SPDK_DEBUGLOG(bdev_daos, "completed IO at %#lx with status %s\n", task->offset, 137 task->status == SPDK_BDEV_IO_STATUS_SUCCESS ? "SUCCESS" : "FAILURE"); 138 139 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(task), task->status); 140 } 141 142 static void 143 bdev_daos_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status) 144 { 145 struct bdev_daos_task *task = (struct bdev_daos_task *)bdev_io->driver_ctx; 146 struct spdk_thread *current_thread = spdk_get_thread(); 147 148 assert(task->submit_td != NULL); 149 150 task->status = status; 151 if (task->submit_td != current_thread) { 152 spdk_thread_send_msg(task->submit_td, _bdev_daos_io_complete, task); 153 } else { 154 _bdev_daos_io_complete(task); 155 } 156 } 157 158 static int64_t 159 bdev_daos_writev(struct bdev_daos *daos, struct bdev_daos_io_channel *ch, 160 struct bdev_daos_task *task, 161 struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t offset) 162 { 163 int rc; 164 struct iovec *io = iov; 165 166 SPDK_DEBUGLOG(bdev_daos, "write %d iovs size %lu to off: %#lx\n", 167 iovcnt, nbytes, offset); 168 169 assert(ch != NULL); 170 assert(daos != NULL); 171 assert(task != NULL); 172 assert(iov != NULL); 173 174 if (iovcnt > BDEV_DAOS_IOVECS_MAX) { 175 SPDK_ERRLOG("iovs number [%d] exceeds max allowed limit [%d]\n", iovcnt, 176 BDEV_DAOS_IOVECS_MAX); 177 return -E2BIG; 178 } 179 180 if ((rc = daos_event_init(&task->ev, ch->queue, NULL))) { 181 SPDK_ERRLOG("%s: could not initialize async event: " DF_RC "\n", 182 daos->disk.name, DP_RC(rc)); 183 return -EINVAL; 184 } 185 186 for (int i = 0; i < iovcnt; i++, iov++) { 187 d_iov_set(&(task->diovs[i]), io->iov_base, io->iov_len); 188 } 189 190 task->sgl.sg_nr = iovcnt; 191 task->sgl.sg_nr_out = 0; 192 task->sgl.sg_iovs = task->diovs; 193 task->offset = offset; 194 195 if ((rc = dfs_write(ch->dfs, ch->obj, &task->sgl, offset, &task->ev))) { 196 SPDK_ERRLOG("%s: could not start async write: " DF_RC "\n", 197 daos->disk.name, DP_RC(rc)); 198 daos_event_fini(&task->ev); 199 return -EINVAL; 200 } 201 202 return nbytes; 203 } 204 205 static int64_t 206 bdev_daos_readv(struct bdev_daos *daos, struct bdev_daos_io_channel *ch, 207 struct bdev_daos_task *task, 208 struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t offset) 209 { 210 int rc; 211 struct iovec *io = iov; 212 213 SPDK_DEBUGLOG(bdev_daos, "read %d iovs size %lu to off: %#lx\n", 214 iovcnt, nbytes, offset); 215 216 assert(ch != NULL); 217 assert(daos != NULL); 218 assert(task != NULL); 219 assert(iov != NULL); 220 221 if (iovcnt > BDEV_DAOS_IOVECS_MAX) { 222 SPDK_ERRLOG("iovs number [%d] exceeds max allowed limit [%d]\n", iovcnt, 223 BDEV_DAOS_IOVECS_MAX); 224 return -E2BIG; 225 } 226 227 if ((rc = daos_event_init(&task->ev, ch->queue, NULL))) { 228 SPDK_ERRLOG("%s: could not initialize async event: " DF_RC "\n", 229 daos->disk.name, DP_RC(rc)); 230 return -EINVAL; 231 } 232 233 for (int i = 0; i < iovcnt; i++, io++) { 234 d_iov_set(&(task->diovs[i]), io->iov_base, io->iov_len); 235 } 236 237 task->sgl.sg_nr = iovcnt; 238 task->sgl.sg_nr_out = 0; 239 task->sgl.sg_iovs = task->diovs; 240 task->offset = offset; 241 242 if ((rc = dfs_read(ch->dfs, ch->obj, &task->sgl, offset, &task->read_size, &task->ev))) { 243 SPDK_ERRLOG("%s: could not start async read: " DF_RC "\n", 244 daos->disk.name, DP_RC(rc)); 245 daos_event_fini(&task->ev); 246 return -EINVAL; 247 } 248 249 return nbytes; 250 } 251 252 static void 253 bdev_daos_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, 254 bool success) 255 { 256 int64_t rc; 257 struct bdev_daos_io_channel *dch = spdk_io_channel_get_ctx(ch); 258 259 if (!success) { 260 bdev_daos_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 261 return; 262 } 263 264 rc = bdev_daos_readv((struct bdev_daos *)bdev_io->bdev->ctxt, 265 dch, 266 (struct bdev_daos_task *)bdev_io->driver_ctx, 267 bdev_io->u.bdev.iovs, 268 bdev_io->u.bdev.iovcnt, 269 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen, 270 bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen); 271 272 if (rc < 0) { 273 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 274 return; 275 } 276 } 277 278 static void 279 _bdev_daos_get_io_inflight(struct spdk_io_channel_iter *i) 280 { 281 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 282 struct bdev_daos_io_channel *dch = spdk_io_channel_get_ctx(ch); 283 int io_inflight = daos_eq_query(dch->queue, DAOS_EQR_WAITING, 0, NULL); 284 285 if (io_inflight > 0) { 286 spdk_for_each_channel_continue(i, -1); 287 return; 288 } 289 290 spdk_for_each_channel_continue(i, 0); 291 } 292 293 static int bdev_daos_reset_retry_timer(void *arg); 294 295 static void 296 _bdev_daos_get_io_inflight_done(struct spdk_io_channel_iter *i, int status) 297 { 298 struct bdev_daos *daos = spdk_io_channel_iter_get_ctx(i); 299 300 if (status == -1) { 301 daos->reset_retry_timer = SPDK_POLLER_REGISTER(bdev_daos_reset_retry_timer, daos, 1000); 302 return; 303 } 304 305 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(daos->reset_task), SPDK_BDEV_IO_STATUS_SUCCESS); 306 } 307 308 static int 309 bdev_daos_reset_retry_timer(void *arg) 310 { 311 struct bdev_daos *daos = arg; 312 313 if (daos->reset_retry_timer) { 314 spdk_poller_unregister(&daos->reset_retry_timer); 315 } 316 317 spdk_for_each_channel(daos, 318 _bdev_daos_get_io_inflight, 319 daos, 320 _bdev_daos_get_io_inflight_done); 321 322 return SPDK_POLLER_BUSY; 323 } 324 325 static void 326 bdev_daos_reset(struct bdev_daos *daos, struct bdev_daos_task *task) 327 { 328 assert(daos != NULL); 329 assert(task != NULL); 330 331 daos->reset_task = task; 332 bdev_daos_reset_retry_timer(daos); 333 } 334 335 336 static int64_t 337 bdev_daos_unmap(struct bdev_daos_io_channel *ch, uint64_t nbytes, 338 uint64_t offset) 339 { 340 SPDK_DEBUGLOG(bdev_daos, "unmap at %#lx with size %#lx\n", offset, nbytes); 341 return dfs_punch(ch->dfs, ch->obj, offset, nbytes); 342 } 343 344 static void 345 _bdev_daos_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 346 { 347 struct bdev_daos_io_channel *dch = spdk_io_channel_get_ctx(ch); 348 349 int64_t rc; 350 switch (bdev_io->type) { 351 case SPDK_BDEV_IO_TYPE_READ: 352 spdk_bdev_io_get_buf(bdev_io, bdev_daos_get_buf_cb, 353 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 354 break; 355 356 case SPDK_BDEV_IO_TYPE_WRITE: 357 rc = bdev_daos_writev((struct bdev_daos *)bdev_io->bdev->ctxt, 358 dch, 359 (struct bdev_daos_task *)bdev_io->driver_ctx, 360 bdev_io->u.bdev.iovs, 361 bdev_io->u.bdev.iovcnt, 362 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen, 363 bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen); 364 if (rc < 0) { 365 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 366 return; 367 } 368 break; 369 370 case SPDK_BDEV_IO_TYPE_RESET: 371 /* Can't cancel in-flight requests, but can wait for their completions */ 372 bdev_daos_reset((struct bdev_daos *)bdev_io->bdev->ctxt, 373 (struct bdev_daos_task *)bdev_io->driver_ctx); 374 break; 375 376 case SPDK_BDEV_IO_TYPE_FLUSH: 377 /* NOOP because DAOS requests land on PMEM and writes are persistent upon completion */ 378 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 379 break; 380 381 case SPDK_BDEV_IO_TYPE_UNMAP: 382 rc = bdev_daos_unmap(dch, 383 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen, 384 bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen); 385 if (!rc) { 386 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 387 } else { 388 SPDK_DEBUGLOG(bdev_daos, "%s: could not unmap: " DF_RC "\n", 389 dch->disk->disk.name, DP_RC((int)rc)); 390 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 391 } 392 393 break; 394 395 default: 396 SPDK_ERRLOG("Wrong io type\n"); 397 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 398 break; 399 } 400 } 401 402 static void 403 bdev_daos_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 404 { 405 struct bdev_daos_task *task = (struct bdev_daos_task *)bdev_io->driver_ctx; 406 struct spdk_thread *submit_td = spdk_io_channel_get_thread(ch); 407 408 assert(task != NULL); 409 410 task->submit_td = submit_td; 411 task->bdev_io = bdev_io; 412 413 _bdev_daos_submit_request(ch, bdev_io); 414 } 415 416 #define POLLING_EVENTS_NUM 64 417 418 static int 419 bdev_daos_channel_poll(void *arg) 420 { 421 daos_event_t *evp[POLLING_EVENTS_NUM]; 422 struct bdev_daos_io_channel *ch = arg; 423 424 assert(ch != NULL); 425 assert(ch->disk != NULL); 426 427 int rc = daos_eq_poll(ch->queue, 0, DAOS_EQ_NOWAIT, 428 POLLING_EVENTS_NUM, evp); 429 430 if (rc < 0) { 431 SPDK_DEBUGLOG(bdev_daos, "%s: could not poll daos event queue: " DF_RC "\n", 432 ch->disk->disk.name, DP_RC(rc)); 433 /* 434 * TODO: There are cases when this is self healing, e.g. 435 * brief network issues, DAOS agent restarting etc. 436 * However, if the issue persists over some time better would be 437 * to remove a bdev or the whole controller 438 */ 439 return SPDK_POLLER_BUSY; 440 } 441 442 for (int i = 0; i < rc; ++i) { 443 struct bdev_daos_task *task = container_of(evp[i], struct bdev_daos_task, ev); 444 enum spdk_bdev_io_status status = SPDK_BDEV_IO_STATUS_SUCCESS; 445 446 assert(task != NULL); 447 448 if (task->ev.ev_error != DER_SUCCESS) { 449 status = SPDK_BDEV_IO_STATUS_FAILED; 450 } 451 452 daos_event_fini(&task->ev); 453 bdev_daos_io_complete(task->bdev_io, status); 454 } 455 456 return rc > 0 ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE; 457 } 458 459 static bool 460 bdev_daos_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) 461 { 462 switch (io_type) { 463 case SPDK_BDEV_IO_TYPE_READ: 464 case SPDK_BDEV_IO_TYPE_WRITE: 465 case SPDK_BDEV_IO_TYPE_RESET: 466 case SPDK_BDEV_IO_TYPE_FLUSH: 467 case SPDK_BDEV_IO_TYPE_UNMAP: 468 return true; 469 470 default: 471 return false; 472 } 473 } 474 475 static struct spdk_io_channel * 476 bdev_daos_get_io_channel(void *ctx) 477 { 478 return spdk_get_io_channel(ctx); 479 } 480 481 static void 482 bdev_daos_write_json_config(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 483 { 484 char uuid_str[SPDK_UUID_STRING_LEN]; 485 struct bdev_daos *daos = bdev->ctxt; 486 487 spdk_json_write_object_begin(w); 488 489 spdk_json_write_named_string(w, "method", "bdev_daos_create"); 490 491 spdk_json_write_named_object_begin(w, "params"); 492 spdk_json_write_named_string(w, "name", bdev->name); 493 spdk_json_write_named_string(w, "pool", daos->pool_name); 494 spdk_json_write_named_string(w, "cont", daos->cont_name); 495 spdk_json_write_named_uint64(w, "num_blocks", bdev->blockcnt); 496 spdk_json_write_named_uint32(w, "block_size", bdev->blocklen); 497 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid); 498 spdk_json_write_named_string(w, "uuid", uuid_str); 499 500 spdk_json_write_object_end(w); 501 502 spdk_json_write_object_end(w); 503 } 504 505 static const struct spdk_bdev_fn_table daos_fn_table = { 506 .destruct = bdev_daos_destruct, 507 .submit_request = bdev_daos_submit_request, 508 .io_type_supported = bdev_daos_io_type_supported, 509 .get_io_channel = bdev_daos_get_io_channel, 510 .write_config_json = bdev_daos_write_json_config, 511 }; 512 513 static void * 514 _bdev_daos_io_channel_create_cb(void *ctx) 515 { 516 int rc = 0 ; 517 struct bdev_daos_io_channel *ch = ctx; 518 struct bdev_daos *daos = ch->disk; 519 520 daos_pool_info_t pinfo; 521 daos_cont_info_t cinfo; 522 daos_oclass_id_t obj_class = OC_SX; 523 524 int fd_oflag = O_CREAT | O_RDWR; 525 mode_t mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO; 526 527 rc = bdev_get_daos_engine(); 528 if (rc) { 529 SPDK_ERRLOG("could not initialize DAOS engine: " DF_RC "\n", DP_RC(rc)); 530 return NULL; 531 } 532 533 SPDK_DEBUGLOG(bdev_daos, "connecting to daos pool '%s'\n", daos->pool_name); 534 if ((rc = daos_pool_connect(daos->pool_name, NULL, DAOS_PC_RW, &ch->pool, &pinfo, NULL))) { 535 SPDK_ERRLOG("%s: could not connect to daos pool: " DF_RC "\n", 536 daos->disk.name, DP_RC(rc)); 537 return NULL; 538 } 539 SPDK_DEBUGLOG(bdev_daos, "connecting to daos container '%s'\n", daos->cont_name); 540 if ((rc = daos_cont_open(ch->pool, daos->cont_name, DAOS_COO_RW, &ch->cont, &cinfo, NULL))) { 541 SPDK_ERRLOG("%s: could not open daos container: " DF_RC "\n", 542 daos->disk.name, DP_RC(rc)); 543 goto cleanup_pool; 544 } 545 SPDK_DEBUGLOG(bdev_daos, "mounting daos dfs\n"); 546 if ((rc = dfs_mount(ch->pool, ch->cont, O_RDWR, &ch->dfs))) { 547 SPDK_ERRLOG("%s: could not mount daos dfs: " DF_RC "\n", 548 daos->disk.name, DP_RC(rc)); 549 goto cleanup_cont; 550 } 551 SPDK_DEBUGLOG(bdev_daos, "opening dfs object\n"); 552 if ((rc = dfs_open(ch->dfs, NULL, daos->disk.name, mode, fd_oflag, obj_class, 553 0, NULL, &ch->obj))) { 554 SPDK_ERRLOG("%s: could not open dfs object: " DF_RC "\n", 555 daos->disk.name, DP_RC(rc)); 556 goto cleanup_mount; 557 } 558 if ((rc = daos_eq_create(&ch->queue))) { 559 SPDK_ERRLOG("%s: could not create daos event queue: " DF_RC "\n", 560 daos->disk.name, DP_RC(rc)); 561 goto cleanup_obj; 562 } 563 564 return ctx; 565 566 cleanup_obj: 567 dfs_release(ch->obj); 568 cleanup_mount: 569 dfs_umount(ch->dfs); 570 cleanup_cont: 571 daos_cont_close(ch->cont, NULL); 572 cleanup_pool: 573 daos_pool_disconnect(ch->pool, NULL); 574 575 return NULL; 576 } 577 578 static int 579 bdev_daos_io_channel_create_cb(void *io_device, void *ctx_buf) 580 { 581 struct bdev_daos_io_channel *ch = ctx_buf; 582 583 ch->disk = io_device; 584 585 if (spdk_call_unaffinitized(_bdev_daos_io_channel_create_cb, ch) == NULL) { 586 return EINVAL; 587 } 588 589 SPDK_DEBUGLOG(bdev_daos, "%s: starting daos event queue poller\n", 590 ch->disk->disk.name); 591 592 ch->poller = SPDK_POLLER_REGISTER(bdev_daos_channel_poll, ch, 0); 593 594 return 0; 595 } 596 597 static void 598 bdev_daos_io_channel_destroy_cb(void *io_device, void *ctx_buf) 599 { 600 int rc; 601 struct bdev_daos_io_channel *ch = ctx_buf; 602 603 SPDK_DEBUGLOG(bdev_daos, "stopping daos event queue poller\n"); 604 605 spdk_poller_unregister(&ch->poller); 606 607 if ((rc = daos_eq_destroy(ch->queue, DAOS_EQ_DESTROY_FORCE))) { 608 SPDK_ERRLOG("could not destroy daos event queue: " DF_RC "\n", DP_RC(rc)); 609 } 610 if ((rc = dfs_release(ch->obj))) { 611 SPDK_ERRLOG("could not release dfs object: " DF_RC "\n", DP_RC(rc)); 612 } 613 if ((rc = dfs_umount(ch->dfs))) { 614 SPDK_ERRLOG("could not unmount dfs: " DF_RC "\n", DP_RC(rc)); 615 } 616 if ((rc = daos_cont_close(ch->cont, NULL))) { 617 SPDK_ERRLOG("could not close container: " DF_RC "\n", DP_RC(rc)); 618 } 619 if ((rc = daos_pool_disconnect(ch->pool, NULL))) { 620 SPDK_ERRLOG("could not disconnect from pool: " DF_RC "\n", DP_RC(rc)); 621 } 622 rc = bdev_daos_put_engine(); 623 if (rc) { 624 SPDK_ERRLOG("could not de-initialize DAOS engine: " DF_RC "\n", DP_RC(rc)); 625 } 626 } 627 628 int 629 create_bdev_daos(struct spdk_bdev **bdev, 630 const char *name, const struct spdk_uuid *uuid, 631 const char *pool, const char *cont, 632 uint64_t num_blocks, uint32_t block_size) 633 { 634 int rc; 635 size_t len; 636 struct bdev_daos *daos; 637 638 SPDK_NOTICELOG("%s: creating bdev_daos disk on '%s:%s'\n", name, pool, cont); 639 640 if (num_blocks == 0) { 641 SPDK_ERRLOG("Disk num_blocks must be greater than 0"); 642 return -EINVAL; 643 } 644 645 if (block_size % 512) { 646 SPDK_ERRLOG("block size must be 512 bytes aligned\n"); 647 return -EINVAL; 648 } 649 650 if (!name) { 651 SPDK_ERRLOG("device name cannot be empty\n"); 652 return -EINVAL; 653 } 654 655 if (!pool) { 656 SPDK_ERRLOG("daos pool cannot be empty\n"); 657 return -EINVAL; 658 } 659 if (!cont) { 660 SPDK_ERRLOG("daos cont cannot be empty\n"); 661 return -EINVAL; 662 } 663 664 daos = calloc(1, sizeof(*daos)); 665 if (!daos) { 666 SPDK_ERRLOG("calloc() failed\n"); 667 return -ENOMEM; 668 } 669 670 len = strlen(pool); 671 if (len > DAOS_PROP_LABEL_MAX_LEN) { 672 SPDK_ERRLOG("daos pool name is too long\n"); 673 free(daos); 674 return -EINVAL; 675 } 676 memcpy(daos->pool_name, pool, len); 677 678 len = strlen(cont); 679 if (len > DAOS_PROP_LABEL_MAX_LEN) { 680 SPDK_ERRLOG("daos cont name is too long\n"); 681 free(daos); 682 return -EINVAL; 683 } 684 memcpy(daos->cont_name, cont, len); 685 686 daos->disk.name = strdup(name); 687 daos->disk.product_name = "DAOS bdev"; 688 689 daos->disk.write_cache = 0; 690 daos->disk.blocklen = block_size; 691 daos->disk.blockcnt = num_blocks; 692 693 if (uuid) { 694 daos->disk.uuid = *uuid; 695 } else { 696 spdk_uuid_generate(&daos->disk.uuid); 697 } 698 699 daos->disk.ctxt = daos; 700 daos->disk.fn_table = &daos_fn_table; 701 daos->disk.module = &daos_if; 702 703 rc = bdev_get_daos_engine(); 704 if (rc) { 705 SPDK_ERRLOG("could not initialize DAOS engine: " DF_RC "\n", DP_RC(rc)); 706 bdev_daos_free(daos); 707 return rc; 708 } 709 710 spdk_io_device_register(daos, bdev_daos_io_channel_create_cb, 711 bdev_daos_io_channel_destroy_cb, 712 sizeof(struct bdev_daos_io_channel), 713 daos->disk.name); 714 715 716 rc = spdk_bdev_register(&daos->disk); 717 if (rc) { 718 spdk_io_device_unregister(daos, NULL); 719 bdev_daos_free(daos); 720 return rc; 721 } 722 723 *bdev = &(daos->disk); 724 725 return rc; 726 } 727 728 void 729 delete_bdev_daos(struct spdk_bdev *bdev, spdk_delete_daos_complete cb_fn, void *cb_arg) 730 { 731 if (!bdev || bdev->module != &daos_if) { 732 cb_fn(cb_arg, -ENODEV); 733 return; 734 } 735 736 spdk_bdev_unregister(bdev, cb_fn, cb_arg); 737 } 738 739 static int 740 bdev_get_daos_engine(void) 741 { 742 int rc = 0; 743 744 pthread_mutex_lock(&g_bdev_daos_init_mutex); 745 if (g_bdev_daos_init_count++ > 0) { 746 pthread_mutex_unlock(&g_bdev_daos_init_mutex); 747 return 0; 748 } 749 SPDK_DEBUGLOG(bdev_daos, "initializing DAOS engine\n"); 750 751 rc = daos_init(); 752 pthread_mutex_unlock(&g_bdev_daos_init_mutex); 753 754 if (rc != -DER_ALREADY && rc) { 755 return rc; 756 } 757 return 0; 758 } 759 760 static int 761 bdev_daos_put_engine(void) 762 { 763 int rc = 0; 764 765 pthread_mutex_lock(&g_bdev_daos_init_mutex); 766 if (--g_bdev_daos_init_count > 0) { 767 pthread_mutex_unlock(&g_bdev_daos_init_mutex); 768 return 0; 769 } 770 SPDK_DEBUGLOG(bdev_daos, "de-initializing DAOS engine\n"); 771 772 rc = daos_fini(); 773 pthread_mutex_unlock(&g_bdev_daos_init_mutex); 774 775 return rc; 776 } 777 778 static int 779 bdev_daos_initialize(void) 780 { 781 /* DAOS engine and client initialization happens 782 during the first bdev creation */ 783 return 0; 784 } 785 786 SPDK_LOG_REGISTER_COMPONENT(bdev_daos) 787