diff --git a/lib/bdev/virtio/bdev_virtio.c b/lib/bdev/virtio/bdev_virtio.c index c14f1816c..07edfbd27 100644 --- a/lib/bdev/virtio/bdev_virtio.c +++ b/lib/bdev/virtio/bdev_virtio.c @@ -149,10 +149,39 @@ static int bdev_virtio_scsi_ch_create_cb(void *io_device, void *ctx_buf); static void bdev_virtio_scsi_ch_destroy_cb(void *io_device, void *ctx_buf); static void process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq); +static void bdev_virtio_ctrlq_poll(void *arg); -static void +static int virtio_scsi_dev_init(struct virtio_scsi_dev *svdev) { + struct virtio_dev *vdev = &svdev->vdev; + struct virtqueue *ctrlq; + struct spdk_ring *ctrlq_ring; + int rc; + + rc = virtio_dev_restart(vdev, VIRTIO_SCSI_DEV_SUPPORTED_FEATURES); + if (rc != 0) { + return rc; + } + + ctrlq_ring = spdk_ring_create(SPDK_RING_TYPE_MP_SC, CTRLQ_RING_SIZE, + SPDK_ENV_SOCKET_ID_ANY); + if (ctrlq_ring == NULL) { + SPDK_ERRLOG("Failed to allocate send ring for the controlq.\n"); + return -1; + } + + rc = virtio_dev_acquire_queue(vdev, VIRTIO_SCSI_CONTROLQ); + if (rc != 0) { + SPDK_ERRLOG("Failed to acquire the controlq.\n"); + spdk_ring_free(ctrlq_ring); + return -1; + } + + ctrlq = vdev->vqs[VIRTIO_SCSI_CONTROLQ]; + ctrlq->poller_ctx = ctrlq_ring; + ctrlq->poller = spdk_poller_register(bdev_virtio_ctrlq_poll, vdev, CTRLQ_POLL_PERIOD_US); + TAILQ_INIT(&svdev->luns); svdev->scan_ctx = NULL; svdev->removed = false; @@ -162,6 +191,7 @@ virtio_scsi_dev_init(struct virtio_scsi_dev *svdev) sizeof(struct bdev_virtio_io_channel)); TAILQ_INSERT_TAIL(&g_virtio_driver.scsi_devs, &svdev->vdev, tailq); + return 0; } static int @@ -199,8 +229,13 @@ virtio_pci_scsi_dev_create_cb(struct virtio_pci_ctx *pci_ctx) &num_queues, sizeof(num_queues)); vdev->max_queues = SPDK_VIRTIO_SCSI_QUEUE_NUM_FIXED + num_queues; - virtio_scsi_dev_init(svdev); - return 0; + rc = virtio_scsi_dev_init(svdev); + if (rc != 0) { + virtio_dev_destruct(vdev); + free(svdev); + } + + return rc; } static struct virtio_scsi_dev * @@ -226,11 +261,17 @@ virtio_user_scsi_dev_create(const char *name, const char *path, return NULL; } - virtio_scsi_dev_init(svdev); + rc = virtio_scsi_dev_init(svdev); + if (rc != 0) { + virtio_dev_destruct(vdev); + free(svdev); + return NULL; + } + return svdev; } -static int scan_target(struct virtio_scsi_scan_base *base); +static int _virtio_scsi_dev_scan_next(struct virtio_scsi_scan_base *base); static int bdev_virtio_get_ctx_size(void) @@ -697,7 +738,7 @@ bdev_virtio_scsi_ch_destroy_cb(void *io_device, void *ctx_buf) } static void -scan_target_abort(struct virtio_scsi_scan_base *base, int error) +_virtio_scsi_dev_scan_abort(struct virtio_scsi_scan_base *base, int error) { struct virtio_scsi_dev *svdev = base->svdev; struct virtio_scsi_disk *disk; @@ -718,20 +759,17 @@ scan_target_abort(struct virtio_scsi_scan_base *base, int error) } static void -scan_target_finish(struct virtio_scsi_scan_base *base) +_virtio_scsi_dev_scan_finish(struct virtio_scsi_scan_base *base) { struct virtio_scsi_dev *svdev = base->svdev; - struct virtio_dev *vdev = &svdev->vdev; size_t bdevs_cnt = 0; struct spdk_bdev *bdevs[BDEV_VIRTIO_MAX_TARGET]; struct virtio_scsi_disk *disk; - struct virtqueue *ctrlq; - struct spdk_ring *ctrlq_ring; - int rc; + int rc, cb_errnum = 0; base->target++; if (base->target < BDEV_VIRTIO_MAX_TARGET) { - rc = scan_target(base); + rc = _virtio_scsi_dev_scan_next(base); if (rc != 0) { assert(false); } @@ -740,35 +778,13 @@ scan_target_finish(struct virtio_scsi_scan_base *base) spdk_put_io_channel(spdk_io_channel_from_ctx(base->channel)); - ctrlq_ring = spdk_ring_create(SPDK_RING_TYPE_MP_SC, CTRLQ_RING_SIZE, - SPDK_ENV_SOCKET_ID_ANY); - if (ctrlq_ring == NULL) { - SPDK_ERRLOG("Failed to allocate send ring for the controlq.\n"); - virtio_scsi_dev_remove(svdev); - return; - } - - rc = virtio_dev_acquire_queue(vdev, VIRTIO_SCSI_CONTROLQ); - if (rc != 0) { - SPDK_ERRLOG("Failed to acquire the controlq.\n"); - spdk_ring_free(ctrlq_ring); - virtio_scsi_dev_remove(svdev); - return; - } - - ctrlq = vdev->vqs[VIRTIO_SCSI_CONTROLQ]; - ctrlq->poller_ctx = ctrlq_ring; - ctrlq->poller = spdk_poller_register(bdev_virtio_ctrlq_poll, vdev, CTRLQ_POLL_PERIOD_US); - while ((disk = TAILQ_FIRST(&base->found_disks))) { TAILQ_REMOVE(&base->found_disks, disk, link); rc = spdk_bdev_register(&disk->bdev); if (rc) { - spdk_io_device_unregister(base->svdev, NULL); SPDK_ERRLOG("Failed to register bdev name=%s\n", disk->bdev.name); - spdk_ring_free(ctrlq_ring); - scan_target_abort(base, rc); - return; + cb_errnum = rc; + continue; } TAILQ_INSERT_TAIL(&svdev->luns, disk, link); bdevs[bdevs_cnt] = &disk->bdev; @@ -778,7 +794,7 @@ scan_target_finish(struct virtio_scsi_scan_base *base) base->svdev->scan_ctx = NULL; if (base->cb_fn) { - base->cb_fn(base->cb_arg, 0, bdevs, bdevs_cnt); + base->cb_fn(base->cb_arg, cb_errnum, bdevs, bdevs_cnt); } spdk_dma_free(base); @@ -1068,7 +1084,7 @@ alloc_virtio_disk(struct virtio_scsi_scan_base *base) bdev->module = SPDK_GET_BDEV_MODULE(virtio_scsi); TAILQ_INSERT_TAIL(&base->found_disks, disk, link); - scan_target_finish(base); + _virtio_scsi_dev_scan_finish(base); return 0; } @@ -1128,7 +1144,7 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) if (vreq->iov_req.iov_len < sizeof(struct virtio_scsi_cmd_req) || vreq->iov_resp.iov_len < sizeof(struct virtio_scsi_cmd_resp)) { SPDK_ERRLOG("Received target scan message with invalid length.\n"); - scan_target_finish(base); + _virtio_scsi_dev_scan_finish(base); return; } @@ -1144,7 +1160,7 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) SPDK_NOTICELOG("Target %"PRIu8" is present, but unavailable.\n", target_id); SPDK_TRACEDUMP(SPDK_LOG_VIRTIO, "CDB", req->cdb, sizeof(req->cdb)); SPDK_TRACEDUMP(SPDK_LOG_VIRTIO, "SENSE DATA", resp->sense, sizeof(resp->sense)); - scan_target_finish(base); + _virtio_scsi_dev_scan_finish(base); return; } @@ -1181,12 +1197,12 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq) } if (rc < 0) { - scan_target_finish(base); + _virtio_scsi_dev_scan_finish(base); } } static int -scan_target(struct virtio_scsi_scan_base *base) +_virtio_scsi_dev_scan_next(struct virtio_scsi_scan_base *base) { struct iovec *iov; struct virtio_req *vreq; @@ -1293,14 +1309,19 @@ out: } static int -bdev_virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb cb_fn, - void *cb_arg) +virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb cb_fn, + void *cb_arg) { - struct virtio_dev *vdev = &svdev->vdev; - struct virtio_scsi_scan_base *base = spdk_dma_zmalloc(sizeof(*base), 64, NULL); + struct virtio_scsi_scan_base *base; struct spdk_io_channel *io_ch; int rc; + io_ch = spdk_get_io_channel(svdev); + if (io_ch == NULL) { + return -EBUSY; + } + + base = spdk_dma_zmalloc(sizeof(*base), 64, NULL); if (base == NULL) { SPDK_ERRLOG("couldn't allocate memory for scsi target scan.\n"); return -ENOMEM; @@ -1309,26 +1330,13 @@ bdev_virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb c base->cb_fn = cb_fn; base->cb_arg = cb_arg; - rc = virtio_dev_restart(vdev, VIRTIO_SCSI_DEV_SUPPORTED_FEATURES); - if (rc != 0) { - spdk_dma_free(base); - return rc; - } - base->svdev = svdev; TAILQ_INIT(&base->found_disks); - io_ch = spdk_get_io_channel(base->svdev); - if (io_ch == NULL) { - /* TODO: do scan on other core */ - spdk_dma_free(base); - return -EBUSY; - } - base->channel = spdk_io_channel_get_ctx(io_ch); svdev->scan_ctx = base; - rc = scan_target(base); + rc = _virtio_scsi_dev_scan_next(base); if (rc) { SPDK_ERRLOG("Failed to start target scan.\n"); spdk_put_io_channel(io_ch); @@ -1377,7 +1385,7 @@ bdev_virtio_initialize(void) /* Initialize all created devices and scan available targets */ TAILQ_FOREACH(vdev, &g_virtio_driver.scsi_devs, tailq) { svdev = virtio_dev_to_scsi(vdev); - rc = bdev_virtio_scsi_dev_scan(svdev, bdev_virtio_initial_scan_complete, NULL); + rc = virtio_scsi_dev_scan(svdev, bdev_virtio_initial_scan_complete, NULL); if (rc != 0) { goto out; } @@ -1452,7 +1460,7 @@ virtio_scsi_dev_remove(struct virtio_scsi_dev *svdev) scan_ctx = svdev->scan_ctx; if (scan_ctx) { - scan_target_abort(scan_ctx, -EINTR); + _virtio_scsi_dev_scan_abort(scan_ctx, -EINTR); } TAILQ_FOREACH_SAFE(disk, &svdev->luns, link, disk_tmp) { @@ -1495,7 +1503,7 @@ bdev_virtio_scsi_dev_create(const char *base_name, const char *path, unsigned nu return -1; } - rc = bdev_virtio_scsi_dev_scan(svdev, cb_fn, cb_arg); + rc = virtio_scsi_dev_scan(svdev, cb_fn, cb_arg); if (rc) { virtio_scsi_dev_remove(svdev); }