bdev/virtio: reuse io_channels for the target scan
Rather than acquiring an exclusive virtqueue for the target scan, (re)use an existing one from io_channel on the scanning thread. The goal is to be able to rescan the virtio device in runtime (hot-attach/detach). Now that scan can be done on existing queues, it is no longer guaranteed that rings have enough space to enqueue all requests. This will be fixed in subsequent patches. Change-Id: I0a39460c0ddb52592ae6828e5a7f51056ada2696 Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/390111 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
527cd3ed83
commit
fcf3af24ff
@ -103,8 +103,8 @@ struct virtio_scsi_scan_info {
|
||||
struct virtio_scsi_scan_base {
|
||||
struct virtio_scsi_dev *svdev;
|
||||
|
||||
/** Virtqueue used for the scan I/O. */
|
||||
struct virtqueue *vq;
|
||||
/** I/O channel used for the scan I/O. */
|
||||
struct bdev_virtio_io_channel *channel;
|
||||
|
||||
bdev_virtio_create_cb cb_fn;
|
||||
void *cb_arg;
|
||||
@ -145,6 +145,24 @@ static bool g_bdev_virtio_finish = false;
|
||||
|
||||
static void virtio_scsi_dev_unregister_cb(void *io_device);
|
||||
static void virtio_scsi_dev_remove(struct virtio_scsi_dev *svdev);
|
||||
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
|
||||
virtio_scsi_dev_init(struct virtio_scsi_dev *svdev)
|
||||
{
|
||||
TAILQ_INIT(&svdev->luns);
|
||||
svdev->scan_ctx = NULL;
|
||||
svdev->removed = false;
|
||||
|
||||
spdk_io_device_register(svdev, bdev_virtio_scsi_ch_create_cb,
|
||||
bdev_virtio_scsi_ch_destroy_cb,
|
||||
sizeof(struct bdev_virtio_io_channel));
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_virtio_driver.scsi_devs, &svdev->vdev, tailq);
|
||||
}
|
||||
|
||||
static int
|
||||
virtio_pci_scsi_dev_create_cb(struct virtio_pci_ctx *pci_ctx)
|
||||
@ -162,10 +180,6 @@ virtio_pci_scsi_dev_create_cb(struct virtio_pci_ctx *pci_ctx)
|
||||
return -1;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&svdev->luns);
|
||||
svdev->scan_ctx = NULL;
|
||||
svdev->removed = false;
|
||||
|
||||
vdev = &svdev->vdev;
|
||||
name = spdk_sprintf_alloc("VirtioScsi%"PRIu32, pci_dev_counter++);
|
||||
if (name == NULL) {
|
||||
@ -185,7 +199,7 @@ 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;
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_virtio_driver.scsi_devs, vdev, tailq);
|
||||
virtio_scsi_dev_init(svdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -203,10 +217,6 @@ virtio_user_scsi_dev_create(const char *name, const char *path,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&svdev->luns);
|
||||
svdev->scan_ctx = NULL;
|
||||
svdev->removed = false;
|
||||
|
||||
vdev = &svdev->vdev;
|
||||
rc = virtio_user_dev_init(vdev, name, path, num_queues, queue_size,
|
||||
SPDK_VIRTIO_SCSI_QUEUE_NUM_FIXED);
|
||||
@ -216,8 +226,7 @@ virtio_user_scsi_dev_create(const char *name, const char *path,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
TAILQ_INSERT_TAIL(&g_virtio_driver.scsi_devs, vdev, tailq);
|
||||
virtio_scsi_dev_init(svdev);
|
||||
return svdev;
|
||||
}
|
||||
|
||||
@ -555,11 +564,18 @@ static void
|
||||
bdev_virtio_poll(void *arg)
|
||||
{
|
||||
struct bdev_virtio_io_channel *ch = arg;
|
||||
struct virtio_scsi_dev *svdev = ch->svdev;
|
||||
struct virtio_req *req[32];
|
||||
uint16_t i, cnt;
|
||||
|
||||
cnt = virtio_recv_pkts(ch->vq, req, SPDK_COUNTOF(req));
|
||||
for (i = 0; i < cnt; ++i) {
|
||||
if (spdk_unlikely(svdev->scan_ctx &&
|
||||
req[i] == &svdev->scan_ctx->io_ctx.vreq)) {
|
||||
process_scan_resp(svdev->scan_ctx, req[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
bdev_virtio_io_cpl(req[i]);
|
||||
}
|
||||
}
|
||||
@ -684,20 +700,14 @@ static void
|
||||
scan_target_abort(struct virtio_scsi_scan_base *base, int error)
|
||||
{
|
||||
struct virtio_scsi_dev *svdev = base->svdev;
|
||||
struct virtio_dev *vdev = &svdev->vdev;
|
||||
struct virtio_scsi_disk *disk;
|
||||
struct virtqueue *vq;
|
||||
|
||||
while ((disk = TAILQ_FIRST(&base->found_disks))) {
|
||||
TAILQ_REMOVE(&base->found_disks, disk, link);
|
||||
free(disk);
|
||||
}
|
||||
|
||||
vq = base->vq;
|
||||
spdk_poller_unregister(&vq->poller);
|
||||
spdk_dma_free(vq->poller_ctx);
|
||||
vq->poller_ctx = NULL;
|
||||
virtio_dev_release_queue(vdev, vq->vq_queue_index);
|
||||
spdk_put_io_channel(spdk_io_channel_from_ctx(base->channel));
|
||||
|
||||
if (base->cb_fn) {
|
||||
base->cb_fn(base->cb_arg, error, NULL, 0);
|
||||
@ -728,9 +738,7 @@ scan_target_finish(struct virtio_scsi_scan_base *base)
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_poller_unregister(&base->vq->poller);
|
||||
base->vq->poller_ctx = NULL;
|
||||
virtio_dev_release_queue(vdev, base->vq->vq_queue_index);
|
||||
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);
|
||||
@ -752,10 +760,6 @@ scan_target_finish(struct virtio_scsi_scan_base *base)
|
||||
ctrlq->poller_ctx = ctrlq_ring;
|
||||
ctrlq->poller = spdk_poller_register(bdev_virtio_ctrlq_poll, vdev, CTRLQ_POLL_PERIOD_US);
|
||||
|
||||
spdk_io_device_register(base->svdev, bdev_virtio_scsi_ch_create_cb,
|
||||
bdev_virtio_scsi_ch_destroy_cb,
|
||||
sizeof(struct bdev_virtio_io_channel));
|
||||
|
||||
while ((disk = TAILQ_FIRST(&base->found_disks))) {
|
||||
TAILQ_REMOVE(&base->found_disks, disk, link);
|
||||
rc = spdk_bdev_register(&disk->bdev);
|
||||
@ -799,7 +803,7 @@ send_inquiry_vpd(struct virtio_scsi_scan_base *base, uint8_t target_id, struct v
|
||||
inquiry_cdb->page_code = page_code;
|
||||
to_be16(inquiry_cdb->alloc_len, iov[0].iov_len);
|
||||
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
rc = virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
@ -819,7 +823,7 @@ send_read_cap_10(struct virtio_scsi_scan_base *base, uint8_t target_id, struct v
|
||||
iov[0].iov_len = 8;
|
||||
req->cdb[0] = SPDK_SBC_READ_CAPACITY_10;
|
||||
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
rc = virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
@ -841,7 +845,7 @@ send_read_cap_16(struct virtio_scsi_scan_base *base, uint8_t target_id, struct v
|
||||
req->cdb[1] = SPDK_SBC_SAI_READ_CAPACITY_16;
|
||||
to_be32(&req->cdb[10], iov[0].iov_len);
|
||||
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
rc = virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
@ -858,7 +862,7 @@ send_test_unit_ready(struct virtio_scsi_scan_base *base, uint8_t target_id, stru
|
||||
req->lun[1] = target_id;
|
||||
req->cdb[0] = SPDK_SPC_TEST_UNIT_READY;
|
||||
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
rc = virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
@ -876,7 +880,7 @@ send_start_stop_unit(struct virtio_scsi_scan_base *base, uint8_t target_id, stru
|
||||
req->cdb[0] = SPDK_SBC_START_STOP_UNIT;
|
||||
req->cdb[4] = SPDK_SBC_START_STOP_UNIT_START_BIT;
|
||||
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
rc = virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
@ -1145,7 +1149,7 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
|
||||
}
|
||||
|
||||
/* resend the same request */
|
||||
rc = virtio_xmit_pkt(base->vq, vreq);
|
||||
rc = virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
if (rc != 0) {
|
||||
assert(false);
|
||||
}
|
||||
@ -1181,19 +1185,6 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bdev_scan_poll(void *arg)
|
||||
{
|
||||
struct virtio_scsi_scan_base *base = arg;
|
||||
struct virtio_req *req;
|
||||
uint16_t cnt;
|
||||
|
||||
cnt = virtio_recv_pkts(base->vq, &req, 1);
|
||||
if (cnt > 0) {
|
||||
process_scan_resp(base, req);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
scan_target(struct virtio_scsi_scan_base *base)
|
||||
{
|
||||
@ -1232,7 +1223,7 @@ scan_target(struct virtio_scsi_scan_base *base)
|
||||
to_be16(cdb->alloc_len, BDEV_VIRTIO_SCAN_PAYLOAD_SIZE);
|
||||
|
||||
base->retries = SCAN_REQUEST_RETRIES;
|
||||
return virtio_xmit_pkt(base->vq, vreq);
|
||||
return virtio_xmit_pkt(base->channel->vq, vreq);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1307,7 +1298,7 @@ bdev_virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb c
|
||||
{
|
||||
struct virtio_dev *vdev = &svdev->vdev;
|
||||
struct virtio_scsi_scan_base *base = spdk_dma_zmalloc(sizeof(*base), 64, NULL);
|
||||
struct virtqueue *vq;
|
||||
struct spdk_io_channel *io_ch;
|
||||
int rc;
|
||||
|
||||
if (base == NULL) {
|
||||
@ -1327,23 +1318,23 @@ bdev_virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb c
|
||||
base->svdev = svdev;
|
||||
TAILQ_INIT(&base->found_disks);
|
||||
|
||||
rc = virtio_dev_acquire_queue(vdev, VIRTIO_SCSI_REQUESTQ);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("Couldn't acquire requestq for the target scan.\n");
|
||||
io_ch = spdk_get_io_channel(base->svdev);
|
||||
if (io_ch == NULL) {
|
||||
/* TODO: do scan on other core */
|
||||
spdk_dma_free(base);
|
||||
return rc;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
vq = vdev->vqs[VIRTIO_SCSI_REQUESTQ];
|
||||
base->vq = vq;
|
||||
base->channel = spdk_io_channel_get_ctx(io_ch);
|
||||
|
||||
svdev->scan_ctx = base;
|
||||
|
||||
vq->poller_ctx = base;
|
||||
vq->poller = spdk_poller_register(bdev_scan_poll, base, 0);
|
||||
rc = scan_target(base);
|
||||
if (rc) {
|
||||
SPDK_ERRLOG("Failed to start target scan.\n");
|
||||
spdk_put_io_channel(io_ch);
|
||||
spdk_dma_free(base);
|
||||
svdev->scan_ctx = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user