1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "spdk/bdev.h" 9 #include "spdk/endian.h" 10 #include "spdk/env.h" 11 #include "spdk/thread.h" 12 #include "spdk/string.h" 13 #include "spdk/util.h" 14 #include "spdk/json.h" 15 16 #include "spdk_internal/assert.h" 17 #include "spdk/bdev_module.h" 18 #include "spdk/log.h" 19 #include "spdk_internal/virtio.h" 20 #include "spdk_internal/vhost_user.h" 21 22 #include <linux/virtio_blk.h> 23 #include <linux/virtio_ids.h> 24 25 #include "bdev_virtio.h" 26 27 struct virtio_blk_dev { 28 struct virtio_dev vdev; 29 struct spdk_bdev bdev; 30 bool readonly; 31 bool unmap; 32 }; 33 34 struct virtio_blk_io_ctx { 35 struct iovec iov_req; 36 struct iovec iov_resp; 37 struct iovec iov_unmap; 38 struct virtio_blk_outhdr req; 39 struct virtio_blk_discard_write_zeroes unmap; 40 uint8_t resp; 41 }; 42 43 struct bdev_virtio_blk_io_channel { 44 struct virtio_dev *vdev; 45 46 /** Virtqueue exclusively assigned to this channel. */ 47 struct virtqueue *vq; 48 49 /** Virtio response poller. */ 50 struct spdk_poller *poller; 51 }; 52 53 /* Features desired/implemented by this driver. */ 54 #define VIRTIO_BLK_DEV_SUPPORTED_FEATURES \ 55 (1ULL << VIRTIO_BLK_F_SIZE_MAX | \ 56 1ULL << VIRTIO_BLK_F_SEG_MAX | \ 57 1ULL << VIRTIO_BLK_F_BLK_SIZE | \ 58 1ULL << VIRTIO_BLK_F_TOPOLOGY | \ 59 1ULL << VIRTIO_BLK_F_MQ | \ 60 1ULL << VIRTIO_BLK_F_RO | \ 61 1ULL << VIRTIO_BLK_F_DISCARD | \ 62 1ULL << VIRTIO_RING_F_EVENT_IDX | \ 63 1ULL << VHOST_USER_F_PROTOCOL_FEATURES) 64 65 /* 10 sec for max poll period */ 66 #define VIRTIO_BLK_HOTPLUG_POLL_PERIOD_MAX 10000000ULL 67 /* Default poll period is 100ms */ 68 #define VIRTIO_BLK_HOTPLUG_POLL_PERIOD_DEFAULT 100000ULL 69 70 static struct spdk_poller *g_blk_hotplug_poller = NULL; 71 static int g_blk_hotplug_fd = -1; 72 73 static int bdev_virtio_initialize(void); 74 static int bdev_virtio_blk_get_ctx_size(void); 75 76 static struct spdk_bdev_module virtio_blk_if = { 77 .name = "virtio_blk", 78 .module_init = bdev_virtio_initialize, 79 .get_ctx_size = bdev_virtio_blk_get_ctx_size, 80 }; 81 82 SPDK_BDEV_MODULE_REGISTER(virtio_blk, &virtio_blk_if) 83 84 static int bdev_virtio_blk_ch_create_cb(void *io_device, void *ctx_buf); 85 static void bdev_virtio_blk_ch_destroy_cb(void *io_device, void *ctx_buf); 86 87 static struct virtio_blk_io_ctx * 88 bdev_virtio_blk_init_io_vreq(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 89 { 90 struct virtio_blk_outhdr *req; 91 uint8_t *resp; 92 struct virtio_blk_discard_write_zeroes *desc; 93 94 struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx; 95 96 req = &io_ctx->req; 97 resp = &io_ctx->resp; 98 desc = &io_ctx->unmap; 99 100 io_ctx->iov_req.iov_base = req; 101 io_ctx->iov_req.iov_len = sizeof(*req); 102 103 io_ctx->iov_resp.iov_base = resp; 104 io_ctx->iov_resp.iov_len = sizeof(*resp); 105 106 io_ctx->iov_unmap.iov_base = desc; 107 io_ctx->iov_unmap.iov_len = sizeof(*desc); 108 109 memset(req, 0, sizeof(*req)); 110 return io_ctx; 111 } 112 113 static void 114 bdev_virtio_blk_send_io(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 115 { 116 struct bdev_virtio_blk_io_channel *virtio_channel = spdk_io_channel_get_ctx(ch); 117 struct virtqueue *vq = virtio_channel->vq; 118 struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx; 119 int rc; 120 121 rc = virtqueue_req_start(vq, bdev_io, bdev_io->u.bdev.iovcnt + 2); 122 if (rc == -ENOMEM) { 123 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM); 124 return; 125 } else if (rc != 0) { 126 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 127 return; 128 } 129 130 virtqueue_req_add_iovs(vq, &io_ctx->iov_req, 1, SPDK_VIRTIO_DESC_RO); 131 if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP) { 132 virtqueue_req_add_iovs(vq, &io_ctx->iov_unmap, 1, SPDK_VIRTIO_DESC_RO); 133 } else { 134 virtqueue_req_add_iovs(vq, bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, 135 bdev_io->type == SPDK_BDEV_IO_TYPE_READ ? 136 SPDK_VIRTIO_DESC_WR : SPDK_VIRTIO_DESC_RO); 137 } 138 virtqueue_req_add_iovs(vq, &io_ctx->iov_resp, 1, SPDK_VIRTIO_DESC_WR); 139 140 virtqueue_req_flush(vq); 141 } 142 143 static void 144 bdev_virtio_command(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 145 { 146 struct virtio_blk_io_ctx *io_ctx = bdev_virtio_blk_init_io_vreq(ch, bdev_io); 147 struct virtio_blk_outhdr *req = &io_ctx->req; 148 struct virtio_blk_discard_write_zeroes *desc = &io_ctx->unmap; 149 150 if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) { 151 req->type = VIRTIO_BLK_T_IN; 152 } else if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) { 153 req->type = VIRTIO_BLK_T_OUT; 154 } else if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP) { 155 req->type = VIRTIO_BLK_T_DISCARD; 156 desc->sector = bdev_io->u.bdev.offset_blocks * 157 spdk_bdev_get_block_size(bdev_io->bdev) / 512; 158 desc->num_sectors = bdev_io->u.bdev.num_blocks * 159 spdk_bdev_get_block_size(bdev_io->bdev) / 512; 160 desc->flags = 0; 161 } 162 163 req->sector = bdev_io->u.bdev.offset_blocks * 164 spdk_bdev_get_block_size(bdev_io->bdev) / 512; 165 166 bdev_virtio_blk_send_io(ch, bdev_io); 167 } 168 169 static void 170 bdev_virtio_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, 171 bool success) 172 { 173 if (!success) { 174 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 175 return; 176 } 177 178 bdev_virtio_command(ch, bdev_io); 179 } 180 181 static int 182 _bdev_virtio_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 183 { 184 struct virtio_blk_dev *bvdev = bdev_io->bdev->ctxt; 185 186 switch (bdev_io->type) { 187 case SPDK_BDEV_IO_TYPE_READ: 188 spdk_bdev_io_get_buf(bdev_io, bdev_virtio_get_buf_cb, 189 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); 190 return 0; 191 case SPDK_BDEV_IO_TYPE_WRITE: 192 if (bvdev->readonly) { 193 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 194 } else { 195 bdev_virtio_command(ch, bdev_io); 196 } 197 return 0; 198 case SPDK_BDEV_IO_TYPE_RESET: 199 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 200 return 0; 201 case SPDK_BDEV_IO_TYPE_UNMAP: 202 if (bvdev->unmap) { 203 bdev_virtio_command(ch, bdev_io); 204 } else { 205 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 206 } 207 return 0; 208 case SPDK_BDEV_IO_TYPE_FLUSH: 209 default: 210 return -1; 211 } 212 213 SPDK_UNREACHABLE(); 214 } 215 216 static void 217 bdev_virtio_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) 218 { 219 if (_bdev_virtio_submit_request(ch, bdev_io) < 0) { 220 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 221 } 222 } 223 224 static bool 225 bdev_virtio_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) 226 { 227 struct virtio_blk_dev *bvdev = ctx; 228 229 switch (io_type) { 230 case SPDK_BDEV_IO_TYPE_READ: 231 case SPDK_BDEV_IO_TYPE_RESET: 232 return true; 233 case SPDK_BDEV_IO_TYPE_WRITE: 234 return !bvdev->readonly; 235 case SPDK_BDEV_IO_TYPE_UNMAP: 236 return bvdev->unmap; 237 case SPDK_BDEV_IO_TYPE_FLUSH: 238 default: 239 return false; 240 } 241 } 242 243 static struct spdk_io_channel * 244 bdev_virtio_get_io_channel(void *ctx) 245 { 246 struct virtio_blk_dev *bvdev = ctx; 247 248 return spdk_get_io_channel(bvdev); 249 } 250 251 static void 252 virtio_blk_dev_unregister_cb(void *io_device) 253 { 254 struct virtio_blk_dev *bvdev = io_device; 255 struct virtio_dev *vdev = &bvdev->vdev; 256 257 virtio_dev_stop(vdev); 258 virtio_dev_destruct(vdev); 259 spdk_bdev_destruct_done(&bvdev->bdev, 0); 260 free(bvdev); 261 } 262 263 static int 264 bdev_virtio_disk_destruct(void *ctx) 265 { 266 struct virtio_blk_dev *bvdev = ctx; 267 268 spdk_io_device_unregister(bvdev, virtio_blk_dev_unregister_cb); 269 return 1; 270 } 271 272 int 273 bdev_virtio_blk_dev_remove(const char *name, bdev_virtio_remove_cb cb_fn, void *cb_arg) 274 { 275 return spdk_bdev_unregister_by_name(name, &virtio_blk_if, cb_fn, cb_arg); 276 } 277 278 static int 279 bdev_virtio_dump_json_config(void *ctx, struct spdk_json_write_ctx *w) 280 { 281 struct virtio_blk_dev *bvdev = ctx; 282 283 virtio_dev_dump_json_info(&bvdev->vdev, w); 284 return 0; 285 } 286 287 static void 288 bdev_virtio_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 289 { 290 struct virtio_blk_dev *bvdev = bdev->ctxt; 291 292 spdk_json_write_object_begin(w); 293 294 spdk_json_write_named_string(w, "method", "bdev_virtio_attach_controller"); 295 296 spdk_json_write_named_object_begin(w, "params"); 297 spdk_json_write_named_string(w, "name", bvdev->vdev.name); 298 spdk_json_write_named_string(w, "dev_type", "blk"); 299 300 /* Write transport specific parameters. */ 301 bvdev->vdev.backend_ops->write_json_config(&bvdev->vdev, w); 302 303 spdk_json_write_object_end(w); 304 305 spdk_json_write_object_end(w); 306 } 307 308 static const struct spdk_bdev_fn_table virtio_fn_table = { 309 .destruct = bdev_virtio_disk_destruct, 310 .submit_request = bdev_virtio_submit_request, 311 .io_type_supported = bdev_virtio_io_type_supported, 312 .get_io_channel = bdev_virtio_get_io_channel, 313 .dump_info_json = bdev_virtio_dump_json_config, 314 .write_config_json = bdev_virtio_write_config_json, 315 }; 316 317 static void 318 bdev_virtio_io_cpl(struct spdk_bdev_io *bdev_io) 319 { 320 struct virtio_blk_io_ctx *io_ctx = (struct virtio_blk_io_ctx *)bdev_io->driver_ctx; 321 322 spdk_bdev_io_complete(bdev_io, io_ctx->resp == VIRTIO_BLK_S_OK ? 323 SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED); 324 } 325 326 static int 327 bdev_virtio_poll(void *arg) 328 { 329 struct bdev_virtio_blk_io_channel *ch = arg; 330 void *io[32]; 331 uint32_t io_len[32]; 332 uint16_t i, cnt; 333 334 cnt = virtio_recv_pkts(ch->vq, io, io_len, SPDK_COUNTOF(io)); 335 for (i = 0; i < cnt; ++i) { 336 bdev_virtio_io_cpl(io[i]); 337 } 338 339 return cnt; 340 } 341 342 static int 343 bdev_virtio_blk_ch_create_cb(void *io_device, void *ctx_buf) 344 { 345 struct virtio_blk_dev *bvdev = io_device; 346 struct virtio_dev *vdev = &bvdev->vdev; 347 struct bdev_virtio_blk_io_channel *ch = ctx_buf; 348 struct virtqueue *vq; 349 int32_t queue_idx; 350 351 queue_idx = virtio_dev_find_and_acquire_queue(vdev, 0); 352 if (queue_idx < 0) { 353 SPDK_ERRLOG("Couldn't get an unused queue for the io_channel.\n"); 354 return -1; 355 } 356 357 vq = vdev->vqs[queue_idx]; 358 359 ch->vdev = vdev; 360 ch->vq = vq; 361 362 ch->poller = SPDK_POLLER_REGISTER(bdev_virtio_poll, ch, 0); 363 return 0; 364 } 365 366 static void 367 bdev_virtio_blk_ch_destroy_cb(void *io_device, void *ctx_buf) 368 { 369 struct virtio_blk_dev *bvdev = io_device; 370 struct virtio_dev *vdev = &bvdev->vdev; 371 struct bdev_virtio_blk_io_channel *ch = ctx_buf; 372 struct virtqueue *vq = ch->vq; 373 374 spdk_poller_unregister(&ch->poller); 375 virtio_dev_release_queue(vdev, vq->vq_queue_index); 376 } 377 378 static int 379 virtio_blk_dev_init(struct virtio_blk_dev *bvdev, uint16_t max_queues) 380 { 381 struct virtio_dev *vdev = &bvdev->vdev; 382 struct spdk_bdev *bdev = &bvdev->bdev; 383 uint64_t capacity, num_blocks; 384 uint32_t block_size, size_max, seg_max; 385 uint16_t host_max_queues; 386 int rc; 387 388 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE)) { 389 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, blk_size), 390 &block_size, sizeof(block_size)); 391 if (rc) { 392 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc)); 393 return rc; 394 } 395 396 if (block_size == 0 || block_size % 512 != 0) { 397 SPDK_ERRLOG("%s: invalid block size (%"PRIu32"). Must be " 398 "a multiple of 512.\n", vdev->name, block_size); 399 return -EIO; 400 } 401 } else { 402 block_size = 512; 403 } 404 405 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, capacity), 406 &capacity, sizeof(capacity)); 407 if (rc) { 408 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc)); 409 return rc; 410 } 411 412 /* `capacity` is a number of 512-byte sectors. */ 413 num_blocks = capacity * 512 / block_size; 414 if (num_blocks == 0) { 415 SPDK_ERRLOG("%s: size too small (size: %"PRIu64", blocksize: %"PRIu32").\n", 416 vdev->name, capacity * 512, block_size); 417 return -EIO; 418 } 419 420 if ((capacity * 512) % block_size != 0) { 421 SPDK_WARNLOG("%s: size has been rounded down to the nearest block size boundary. " 422 "(block size: %"PRIu32", previous size: %"PRIu64", new size: %"PRIu64")\n", 423 vdev->name, block_size, capacity * 512, num_blocks * block_size); 424 } 425 426 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_MQ)) { 427 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues), 428 &host_max_queues, sizeof(host_max_queues)); 429 if (rc) { 430 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc)); 431 return rc; 432 } 433 } else { 434 host_max_queues = 1; 435 } 436 437 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_SIZE_MAX)) { 438 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, size_max), 439 &size_max, sizeof(size_max)); 440 if (rc) { 441 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc)); 442 return rc; 443 } 444 445 if (spdk_unlikely(size_max < block_size)) { 446 SPDK_WARNLOG("%s: minimum segment size is set to block size %u forcefully.\n", 447 vdev->name, block_size); 448 size_max = block_size; 449 } 450 451 bdev->max_segment_size = size_max; 452 } 453 454 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_SEG_MAX)) { 455 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, seg_max), 456 &seg_max, sizeof(seg_max)); 457 if (rc) { 458 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc)); 459 return rc; 460 } 461 462 if (spdk_unlikely(seg_max == 0)) { 463 SPDK_ERRLOG("%s: virtio blk SEG_MAX can't be 0\n", vdev->name); 464 return -EINVAL; 465 } 466 467 bdev->max_num_segments = seg_max; 468 } 469 470 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_RO)) { 471 bvdev->readonly = true; 472 } 473 474 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) { 475 bvdev->unmap = true; 476 } 477 478 if (max_queues == 0) { 479 SPDK_ERRLOG("%s: requested 0 request queues (%"PRIu16" available).\n", 480 vdev->name, host_max_queues); 481 return -EINVAL; 482 } 483 484 if (max_queues > host_max_queues) { 485 SPDK_WARNLOG("%s: requested %"PRIu16" request queues " 486 "but only %"PRIu16" available.\n", 487 vdev->name, max_queues, host_max_queues); 488 max_queues = host_max_queues; 489 } 490 491 /* bdev is tied with the virtio device; we can reuse the name */ 492 bdev->name = vdev->name; 493 rc = virtio_dev_start(vdev, max_queues, 0); 494 if (rc != 0) { 495 return rc; 496 } 497 498 bdev->product_name = "VirtioBlk Disk"; 499 bdev->write_cache = 0; 500 bdev->blocklen = block_size; 501 bdev->blockcnt = num_blocks; 502 503 bdev->ctxt = bvdev; 504 bdev->fn_table = &virtio_fn_table; 505 bdev->module = &virtio_blk_if; 506 507 spdk_io_device_register(bvdev, bdev_virtio_blk_ch_create_cb, 508 bdev_virtio_blk_ch_destroy_cb, 509 sizeof(struct bdev_virtio_blk_io_channel), 510 vdev->name); 511 512 rc = spdk_bdev_register(bdev); 513 if (rc) { 514 SPDK_ERRLOG("Failed to register bdev name=%s\n", bdev->name); 515 spdk_io_device_unregister(bvdev, NULL); 516 virtio_dev_stop(vdev); 517 return rc; 518 } 519 520 return 0; 521 } 522 523 static struct virtio_blk_dev * 524 virtio_pci_blk_dev_create(const char *name, struct virtio_pci_ctx *pci_ctx) 525 { 526 static int pci_dev_counter = 0; 527 struct virtio_blk_dev *bvdev; 528 struct virtio_dev *vdev; 529 char *default_name = NULL; 530 uint16_t num_queues; 531 int rc; 532 533 bvdev = calloc(1, sizeof(*bvdev)); 534 if (bvdev == NULL) { 535 SPDK_ERRLOG("virtio device calloc failed\n"); 536 return NULL; 537 } 538 vdev = &bvdev->vdev; 539 540 if (name == NULL) { 541 default_name = spdk_sprintf_alloc("VirtioBlk%"PRIu32, pci_dev_counter++); 542 if (default_name == NULL) { 543 free(vdev); 544 return NULL; 545 } 546 name = default_name; 547 } 548 549 rc = virtio_pci_dev_init(vdev, name, pci_ctx); 550 free(default_name); 551 552 if (rc != 0) { 553 free(bvdev); 554 return NULL; 555 } 556 557 rc = virtio_dev_reset(vdev, VIRTIO_BLK_DEV_SUPPORTED_FEATURES); 558 if (rc != 0) { 559 goto fail; 560 } 561 562 /* TODO: add a way to limit usable virtqueues */ 563 if (virtio_dev_has_feature(vdev, VIRTIO_BLK_F_MQ)) { 564 rc = virtio_dev_read_dev_config(vdev, offsetof(struct virtio_blk_config, num_queues), 565 &num_queues, sizeof(num_queues)); 566 if (rc) { 567 SPDK_ERRLOG("%s: config read failed: %s\n", vdev->name, spdk_strerror(-rc)); 568 goto fail; 569 } 570 } else { 571 num_queues = 1; 572 } 573 574 rc = virtio_blk_dev_init(bvdev, num_queues); 575 if (rc != 0) { 576 goto fail; 577 } 578 579 return bvdev; 580 581 fail: 582 vdev->ctx = NULL; 583 virtio_dev_destruct(vdev); 584 free(bvdev); 585 return NULL; 586 } 587 588 static struct virtio_blk_dev * 589 virtio_user_blk_dev_create(const char *name, const char *path, 590 uint16_t num_queues, uint32_t queue_size) 591 { 592 struct virtio_blk_dev *bvdev; 593 int rc; 594 595 bvdev = calloc(1, sizeof(*bvdev)); 596 if (bvdev == NULL) { 597 SPDK_ERRLOG("calloc failed for virtio device %s: %s\n", name, path); 598 return NULL; 599 } 600 601 rc = virtio_user_dev_init(&bvdev->vdev, name, path, queue_size); 602 if (rc != 0) { 603 SPDK_ERRLOG("Failed to create virito device %s: %s\n", name, path); 604 free(bvdev); 605 return NULL; 606 } 607 608 rc = virtio_dev_reset(&bvdev->vdev, VIRTIO_BLK_DEV_SUPPORTED_FEATURES); 609 if (rc != 0) { 610 virtio_dev_destruct(&bvdev->vdev); 611 free(bvdev); 612 return NULL; 613 } 614 615 rc = virtio_blk_dev_init(bvdev, num_queues); 616 if (rc != 0) { 617 virtio_dev_destruct(&bvdev->vdev); 618 free(bvdev); 619 return NULL; 620 } 621 622 return bvdev; 623 } 624 625 struct bdev_virtio_pci_dev_create_ctx { 626 const char *name; 627 struct virtio_blk_dev *ret; 628 }; 629 630 static int 631 bdev_virtio_pci_blk_dev_create_cb(struct virtio_pci_ctx *pci_ctx, void *ctx) 632 { 633 struct bdev_virtio_pci_dev_create_ctx *create_ctx = ctx; 634 635 create_ctx->ret = virtio_pci_blk_dev_create(create_ctx->name, pci_ctx); 636 if (create_ctx->ret == NULL) { 637 return -1; 638 } 639 640 return 0; 641 } 642 643 struct spdk_bdev * 644 bdev_virtio_pci_blk_dev_create(const char *name, struct spdk_pci_addr *pci_addr) 645 { 646 struct bdev_virtio_pci_dev_create_ctx create_ctx; 647 648 create_ctx.name = name; 649 create_ctx.ret = NULL; 650 651 virtio_pci_dev_attach(bdev_virtio_pci_blk_dev_create_cb, &create_ctx, 652 VIRTIO_ID_BLOCK, pci_addr); 653 654 if (create_ctx.ret == NULL) { 655 return NULL; 656 } 657 658 return &create_ctx.ret->bdev; 659 } 660 661 static int 662 bdev_virtio_pci_blk_monitor(void *arg) 663 { 664 const char *vdev_name; 665 struct bdev_virtio_pci_dev_create_ctx create_ctx; 666 667 while ((vdev_name = virtio_pci_dev_event_process(g_blk_hotplug_fd, VIRTIO_ID_BLOCK)) != NULL) { 668 bdev_virtio_blk_dev_remove(vdev_name, NULL, NULL); 669 } 670 671 /* Enumerate virtio pci_blk device */ 672 memset(&create_ctx, 0, sizeof(create_ctx)); 673 virtio_pci_dev_enumerate(bdev_virtio_pci_blk_dev_create_cb, &create_ctx, 674 VIRTIO_ID_BLOCK); 675 676 return SPDK_POLLER_BUSY; 677 } 678 679 int 680 bdev_virtio_pci_blk_set_hotplug(bool enabled, uint64_t period_us) 681 { 682 if (enabled == true && !spdk_process_is_primary()) { 683 return -EPERM; 684 } 685 686 if (g_blk_hotplug_poller) { 687 close(g_blk_hotplug_fd); 688 spdk_poller_unregister(&g_blk_hotplug_poller); 689 } 690 691 if (!enabled) { 692 return 0; 693 } 694 695 g_blk_hotplug_fd = spdk_pci_event_listen(); 696 if (g_blk_hotplug_fd < 0) { 697 return g_blk_hotplug_fd; 698 } 699 700 period_us = period_us ? period_us : VIRTIO_BLK_HOTPLUG_POLL_PERIOD_DEFAULT; 701 period_us = spdk_min(period_us, VIRTIO_BLK_HOTPLUG_POLL_PERIOD_MAX); 702 g_blk_hotplug_poller = spdk_poller_register(bdev_virtio_pci_blk_monitor, NULL, period_us); 703 if (!g_blk_hotplug_poller) { 704 close(g_blk_hotplug_fd); 705 return -1; 706 } 707 708 return 0; 709 } 710 711 static int 712 bdev_virtio_initialize(void) 713 { 714 return 0; 715 } 716 717 struct spdk_bdev * 718 bdev_virtio_user_blk_dev_create(const char *name, const char *path, 719 unsigned num_queues, unsigned queue_size) 720 { 721 struct virtio_blk_dev *bvdev; 722 723 bvdev = virtio_user_blk_dev_create(name, path, num_queues, queue_size); 724 if (bvdev == NULL) { 725 return NULL; 726 } 727 728 return &bvdev->bdev; 729 } 730 731 static int 732 bdev_virtio_blk_get_ctx_size(void) 733 { 734 return sizeof(struct virtio_blk_io_ctx); 735 } 736 737 SPDK_LOG_REGISTER_COMPONENT(virtio_blk) 738