vhost_scsi: implemented abstract vhost event layer
Implemented abstract vhost event layer on top of virtio eventq. This allows us to defer virtio-event-related actions to be called from the vhost poller thread. This is required for hot-attach, for which io_channels have to be created on the I/O thread. This adds full support for hot-attaching and hot-detaching vhost scsi devices. They can be now attached to a controller via RPC at any time. Change-Id: Icf353bfcf69c83ef16b8fc771ea4c487002094f9 Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Signed-off-by: Pawel Kaminski <pawelx.kaminski@intel.com> Reviewed-on: https://review.gerrithub.io/370016 Reviewed-by: Pawel Wodkowski <pawelx.wodkowski@intel.com> Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
40b74cd343
commit
542b541588
@ -46,6 +46,8 @@
|
||||
#include "spdk/vhost.h"
|
||||
#include "vhost_internal.h"
|
||||
|
||||
#include "spdk_internal/assert.h"
|
||||
|
||||
/* Features supported by SPDK VHOST lib. */
|
||||
#define SPDK_VHOST_SCSI_FEATURES ((1ULL << VIRTIO_F_VERSION_1) | \
|
||||
(1ULL << VHOST_F_LOG_ALL) | \
|
||||
@ -75,13 +77,13 @@
|
||||
struct spdk_vhost_scsi_dev {
|
||||
struct spdk_vhost_dev vdev;
|
||||
struct spdk_scsi_dev *scsi_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
|
||||
bool removed_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
|
||||
bool detached_dev[SPDK_VHOST_SCSI_CTRLR_MAX_DEVS];
|
||||
|
||||
struct spdk_ring *task_pool;
|
||||
struct spdk_poller *requestq_poller;
|
||||
struct spdk_poller *mgmt_poller;
|
||||
|
||||
struct spdk_ring *eventq_ring;
|
||||
struct spdk_ring *vhost_events;
|
||||
} __rte_cache_aligned;
|
||||
|
||||
struct spdk_vhost_scsi_task {
|
||||
@ -101,6 +103,18 @@ struct spdk_vhost_scsi_task {
|
||||
struct rte_vhost_vring *vq;
|
||||
};
|
||||
|
||||
enum spdk_vhost_scsi_event_type {
|
||||
SPDK_VHOST_SCSI_EVENT_HOTATTACH,
|
||||
SPDK_VHOST_SCSI_EVENT_HOTDETACH,
|
||||
};
|
||||
|
||||
struct spdk_vhost_scsi_event {
|
||||
enum spdk_vhost_scsi_event_type type;
|
||||
unsigned dev_index;
|
||||
struct spdk_scsi_dev *dev;
|
||||
struct spdk_scsi_lun *lun;
|
||||
};
|
||||
|
||||
static int new_device(int vid);
|
||||
static void destroy_device(int vid);
|
||||
|
||||
@ -147,36 +161,102 @@ spdk_vhost_get_tasks(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_scsi_t
|
||||
}
|
||||
|
||||
static void
|
||||
process_eventq(struct spdk_vhost_scsi_dev *svdev)
|
||||
spdk_vhost_scsi_event_process(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_scsi_event *ev,
|
||||
struct virtio_scsi_event *desc_ev)
|
||||
{
|
||||
int event_id, reason_id;
|
||||
int dev_id, lun_id;
|
||||
|
||||
assert(ev->dev);
|
||||
assert(ev->dev_index < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS);
|
||||
dev_id = ev->dev_index;
|
||||
|
||||
switch (ev->type) {
|
||||
case SPDK_VHOST_SCSI_EVENT_HOTATTACH:
|
||||
event_id = VIRTIO_SCSI_T_TRANSPORT_RESET;
|
||||
reason_id = VIRTIO_SCSI_EVT_RESET_RESCAN;
|
||||
|
||||
spdk_scsi_dev_allocate_io_channels(ev->dev);
|
||||
svdev->scsi_dev[dev_id] = ev->dev;
|
||||
svdev->detached_dev[dev_id] = false;
|
||||
SPDK_NOTICELOG("%s: hot-attached device %d\n", svdev->vdev.name, dev_id);
|
||||
break;
|
||||
case SPDK_VHOST_SCSI_EVENT_HOTDETACH:
|
||||
event_id = VIRTIO_SCSI_T_TRANSPORT_RESET;
|
||||
reason_id = VIRTIO_SCSI_EVT_RESET_REMOVED;
|
||||
|
||||
if (ev->lun == NULL) {
|
||||
svdev->detached_dev[dev_id] = true;
|
||||
SPDK_NOTICELOG("%s: marked 'Dev %d' for hot-detach\n", svdev->vdev.name, dev_id);
|
||||
} else {
|
||||
SPDK_NOTICELOG("%s: hotremoved LUN '%s'\n", svdev->vdev.name, spdk_scsi_lun_get_name(ev->lun));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SPDK_UNREACHABLE();
|
||||
}
|
||||
|
||||
/* some events may apply to the entire device via lun id set to 0 */
|
||||
lun_id = ev->lun == NULL ? 0 : spdk_scsi_lun_get_id(ev->lun);
|
||||
|
||||
if (desc_ev) {
|
||||
desc_ev->event = event_id;
|
||||
desc_ev->lun[0] = 1;
|
||||
desc_ev->lun[1] = dev_id;
|
||||
desc_ev->lun[2] = lun_id >> 8; /* relies on linux kernel implementation */
|
||||
desc_ev->lun[3] = lun_id & 0xFF;
|
||||
memset(&desc_ev->lun[4], 0, 4);
|
||||
desc_ev->reason = reason_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process vhost event, send virtio event
|
||||
*/
|
||||
static void
|
||||
process_event(struct spdk_vhost_scsi_dev *svdev, struct spdk_vhost_scsi_event *ev)
|
||||
{
|
||||
struct rte_vhost_vring *vq;
|
||||
struct vring_desc *desc;
|
||||
struct virtio_scsi_event *ev, *desc_ev;
|
||||
struct virtio_scsi_event *desc_ev;
|
||||
uint32_t req_size;
|
||||
uint16_t req;
|
||||
struct rte_vhost_vring *vq = &svdev->vdev.virtqueue[VIRTIO_SCSI_EVENTQ];
|
||||
|
||||
vq = &svdev->vdev.virtqueue[VIRTIO_SCSI_EVENTQ];
|
||||
|
||||
while (spdk_ring_dequeue(svdev->eventq_ring, (void **)&ev, 1) == 1) {
|
||||
if (spdk_vhost_vq_avail_ring_get(vq, &req, 1) != 1) {
|
||||
SPDK_ERRLOG("Controller %s: Failed to send virtio event (no avail ring entries?).\n",
|
||||
svdev->vdev.name);
|
||||
spdk_dma_free(ev);
|
||||
break;
|
||||
}
|
||||
|
||||
if (spdk_vhost_vq_avail_ring_get(vq, &req, 1) != 1) {
|
||||
SPDK_ERRLOG("%s: no avail virtio eventq ring entries. virtio event won't be sent.\n",
|
||||
svdev->vdev.name);
|
||||
desc = NULL;
|
||||
desc_ev = NULL;
|
||||
req_size = 0;
|
||||
/* even though we can't send virtio event,
|
||||
* the spdk vhost event should still be processed
|
||||
*/
|
||||
} else {
|
||||
desc = spdk_vhost_vq_get_desc(vq, req);
|
||||
desc_ev = spdk_vhost_gpa_to_vva(&svdev->vdev, desc->addr);
|
||||
req_size = sizeof(*desc_ev);
|
||||
|
||||
if (desc->len >= sizeof(*desc_ev) && desc_ev != NULL) {
|
||||
req_size = sizeof(*desc_ev);
|
||||
memcpy(desc_ev, ev, sizeof(*desc_ev));
|
||||
} else {
|
||||
SPDK_ERRLOG("Controller %s: Invalid eventq descriptor.\n", svdev->vdev.name);
|
||||
if (desc->len < sizeof(*desc_ev) || desc_ev == NULL) {
|
||||
SPDK_ERRLOG("%s: invalid eventq descriptor.\n", svdev->vdev.name);
|
||||
desc_ev = NULL;
|
||||
req_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
spdk_vhost_scsi_event_process(svdev, ev, desc_ev);
|
||||
|
||||
if (desc) {
|
||||
spdk_vhost_vq_used_ring_enqueue(&svdev->vdev, vq, req, req_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_eventq(struct spdk_vhost_scsi_dev *svdev)
|
||||
{
|
||||
struct spdk_vhost_scsi_event *ev;
|
||||
|
||||
while (spdk_ring_dequeue(svdev->vhost_events, (void **)&ev, 1) == 1) {
|
||||
process_event(svdev, ev);
|
||||
spdk_dma_free(ev);
|
||||
}
|
||||
}
|
||||
@ -190,55 +270,39 @@ process_removed_devs(struct spdk_vhost_scsi_dev *svdev)
|
||||
for (i = 0; i < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; ++i) {
|
||||
dev = svdev->scsi_dev[i];
|
||||
|
||||
if (dev && svdev->removed_dev[i] && !spdk_scsi_dev_has_pending_tasks(dev)) {
|
||||
if (dev && svdev->detached_dev[i] && !spdk_scsi_dev_has_pending_tasks(dev)) {
|
||||
spdk_scsi_dev_free_io_channels(dev);
|
||||
spdk_scsi_dev_destruct(dev);
|
||||
svdev->scsi_dev[i] = NULL;
|
||||
SPDK_NOTICELOG("%s: hotremoved device 'Dev %u'.\n", svdev->vdev.name, i);
|
||||
SPDK_NOTICELOG("%s: hot-detached 'Dev %d'.\n", svdev->vdev.name, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eventq_enqueue(struct spdk_vhost_scsi_dev *svdev, const struct spdk_scsi_dev *dev,
|
||||
const struct spdk_scsi_lun *lun, uint32_t event, uint32_t reason)
|
||||
enqueue_vhost_event(struct spdk_vhost_scsi_dev *svdev, enum spdk_vhost_scsi_event_type type,
|
||||
int dev_index, struct spdk_scsi_dev *dev, struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct virtio_scsi_event *ev;
|
||||
int dev_id, lun_id;
|
||||
struct spdk_vhost_scsi_event *ev;
|
||||
|
||||
if (dev == NULL) {
|
||||
SPDK_ERRLOG("%s: eventq device cannot be NULL.\n", svdev->vdev.name);
|
||||
SPDK_ERRLOG("%s: vhost event device cannot be NULL.\n", svdev->vdev.name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (dev_id = 0; dev_id < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; dev_id++) {
|
||||
if (svdev->scsi_dev[dev_id] == dev) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev_id == SPDK_VHOST_SCSI_CTRLR_MAX_DEVS) {
|
||||
SPDK_ERRLOG("Dev %s is not a part of vhost scsi controller '%s'.\n", spdk_scsi_dev_get_name(dev),
|
||||
svdev->vdev.name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* some events may apply to the entire device via lun id set to 0 */
|
||||
lun_id = lun == NULL ? 0 : spdk_scsi_lun_get_id(lun);
|
||||
|
||||
ev = spdk_dma_zmalloc(sizeof(*ev), SPDK_CACHE_LINE_SIZE, NULL);
|
||||
assert(ev);
|
||||
if (ev == NULL) {
|
||||
SPDK_ERRLOG("%s: failed to alloc vhost event.\n", svdev->vdev.name);
|
||||
return;
|
||||
}
|
||||
|
||||
ev->event = event;
|
||||
ev->lun[0] = 1;
|
||||
ev->lun[1] = dev_id;
|
||||
ev->lun[2] = lun_id >> 8; /* relies on linux kernel implementation */
|
||||
ev->lun[3] = lun_id & 0xFF;
|
||||
ev->reason = reason;
|
||||
ev->type = type;
|
||||
ev->dev_index = dev_index;
|
||||
ev->dev = dev;
|
||||
ev->lun = lun;
|
||||
|
||||
if (spdk_ring_enqueue(svdev->eventq_ring, (void **)&ev, 1) != 1) {
|
||||
SPDK_ERRLOG("Controller %s: Failed to inform guest about LUN #%d removal (no room in ring?).\n",
|
||||
svdev->vdev.name, lun_id);
|
||||
if (spdk_ring_enqueue(svdev->vhost_events, (void **)&ev, 1) != 1) {
|
||||
SPDK_ERRLOG("%s: failed to enqueue vhost event (no room in ring?).\n", svdev->vdev.name);
|
||||
spdk_dma_free(ev);
|
||||
}
|
||||
}
|
||||
@ -329,10 +393,10 @@ spdk_vhost_scsi_task_init_target(struct spdk_vhost_scsi_task *task, const __u8 *
|
||||
dev = task->svdev->scsi_dev[lun[1]];
|
||||
task->scsi_dev = dev;
|
||||
if (dev == NULL) {
|
||||
/* If dev has been hotremoved, return 0 to allow sending additional
|
||||
* hotremove event via sense codes.
|
||||
/* If dev has been hot-detached, return 0 to allow sending additional
|
||||
* scsi hotremove event via sense codes.
|
||||
*/
|
||||
return task->svdev->removed_dev[lun[1]] ? 0 : -1;
|
||||
return task->svdev->detached_dev[lun[1]] ? 0 : -1;
|
||||
}
|
||||
|
||||
task->scsi.target_port = spdk_scsi_dev_find_port_by_id(task->scsi_dev, 0);
|
||||
@ -658,7 +722,6 @@ static void
|
||||
remove_vdev_cb(void *arg)
|
||||
{
|
||||
struct spdk_vhost_scsi_dev *svdev = arg;
|
||||
void *ev;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; i++) {
|
||||
@ -670,11 +733,6 @@ remove_vdev_cb(void *arg)
|
||||
|
||||
SPDK_NOTICELOG("Stopping poller for vhost controller %s\n", svdev->vdev.name);
|
||||
spdk_vhost_dev_mem_unregister(&svdev->vdev);
|
||||
|
||||
/* Cleanup not sent events */
|
||||
while (spdk_ring_dequeue(svdev->eventq_ring, &ev, 1) == 1) {
|
||||
spdk_dma_free(ev);
|
||||
}
|
||||
}
|
||||
|
||||
static struct spdk_vhost_scsi_dev *
|
||||
@ -704,17 +762,11 @@ spdk_vhost_scsi_dev_construct(const char *name, uint64_t cpumask)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
svdev->eventq_ring = spdk_ring_create(SPDK_RING_TYPE_MP_SC, 16, SOCKET_ID_ANY);
|
||||
if (svdev->eventq_ring == NULL) {
|
||||
spdk_dma_free(svdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = spdk_vhost_dev_construct(&svdev->vdev, name, cpumask, SPDK_VHOST_DEV_T_SCSI,
|
||||
&spdk_vhost_scsi_device_backend);
|
||||
|
||||
if (rc) {
|
||||
spdk_ring_free(svdev->eventq_ring);
|
||||
spdk_ring_free(svdev->vhost_events);
|
||||
spdk_dma_free(svdev);
|
||||
return rc;
|
||||
}
|
||||
@ -743,7 +795,7 @@ spdk_vhost_scsi_dev_remove(struct spdk_vhost_dev *vdev)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
spdk_ring_free(svdev->eventq_ring);
|
||||
spdk_ring_free(svdev->vhost_events);
|
||||
spdk_dma_free(svdev);
|
||||
return 0;
|
||||
}
|
||||
@ -763,16 +815,35 @@ static void
|
||||
spdk_vhost_scsi_lun_hotremove(const struct spdk_scsi_lun *lun, void *arg)
|
||||
{
|
||||
struct spdk_vhost_scsi_dev *svdev = arg;
|
||||
const struct spdk_scsi_dev *scsi_dev;
|
||||
unsigned scsi_dev_num;
|
||||
|
||||
assert(lun != NULL);
|
||||
assert(svdev != NULL);
|
||||
if ((svdev->vdev.negotiated_features & (1ULL << VIRTIO_SCSI_F_HOTPLUG)) == 0) {
|
||||
SPDK_WARNLOG("Controller %s: hotremove is not supported\n", svdev->vdev.name);
|
||||
SPDK_WARNLOG("%s: hotremove is not enabled for this controller.\n", svdev->vdev.name);
|
||||
return;
|
||||
}
|
||||
|
||||
eventq_enqueue(svdev, spdk_scsi_lun_get_dev(lun), lun, VIRTIO_SCSI_T_TRANSPORT_RESET,
|
||||
VIRTIO_SCSI_EVT_RESET_REMOVED);
|
||||
scsi_dev = spdk_scsi_lun_get_dev(lun);
|
||||
|
||||
for (scsi_dev_num = 0; scsi_dev_num < SPDK_VHOST_SCSI_CTRLR_MAX_DEVS; ++scsi_dev_num) {
|
||||
if (svdev->scsi_dev[scsi_dev_num] == scsi_dev) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (scsi_dev_num == SPDK_VHOST_SCSI_CTRLR_MAX_DEVS) {
|
||||
SPDK_ERRLOG("%s: '%s' is not a part of this controller.\n", svdev->vdev.name,
|
||||
spdk_scsi_dev_get_name(scsi_dev));
|
||||
return;
|
||||
}
|
||||
|
||||
enqueue_vhost_event(svdev, SPDK_VHOST_SCSI_EVENT_HOTDETACH, scsi_dev_num,
|
||||
(struct spdk_scsi_dev *) scsi_dev, (struct spdk_scsi_lun *) lun);
|
||||
|
||||
SPDK_NOTICELOG("%s: queued LUN '%s' for hotremove\n", svdev->vdev.name,
|
||||
spdk_scsi_dev_get_name(scsi_dev));
|
||||
}
|
||||
|
||||
int
|
||||
@ -780,6 +851,7 @@ spdk_vhost_scsi_dev_add_dev(const char *ctrlr_name, unsigned scsi_dev_num, const
|
||||
{
|
||||
struct spdk_vhost_scsi_dev *svdev;
|
||||
struct spdk_vhost_dev *vdev;
|
||||
struct spdk_scsi_dev *scsi_dev;
|
||||
char dev_name[SPDK_SCSI_DEV_MAX_NAME];
|
||||
int lun_id_list[1];
|
||||
char *lun_names_list[1];
|
||||
@ -814,9 +886,10 @@ spdk_vhost_scsi_dev_add_dev(const char *ctrlr_name, unsigned scsi_dev_num, const
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (vdev->lcore != -1) {
|
||||
SPDK_ERRLOG("Controller %s is in use and hotplug is not supported\n", ctrlr_name);
|
||||
return -ENODEV;
|
||||
if (vdev->lcore != -1 && (svdev->vdev.negotiated_features & (1ULL << VIRTIO_SCSI_F_HOTPLUG)) == 0) {
|
||||
SPDK_ERRLOG("%s: 'Dev %u' is in use and hot-attach is not enabled for this controller\n",
|
||||
ctrlr_name, scsi_dev_num);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (svdev->scsi_dev[scsi_dev_num] != NULL) {
|
||||
@ -831,16 +904,23 @@ spdk_vhost_scsi_dev_add_dev(const char *ctrlr_name, unsigned scsi_dev_num, const
|
||||
lun_id_list[0] = 0;
|
||||
lun_names_list[0] = (char *)lun_name;
|
||||
|
||||
svdev->removed_dev[scsi_dev_num] = false;
|
||||
svdev->scsi_dev[scsi_dev_num] = spdk_scsi_dev_construct(dev_name, lun_names_list, lun_id_list, 1,
|
||||
SPDK_SPC_PROTOCOL_IDENTIFIER_SAS, spdk_vhost_scsi_lun_hotremove, svdev);
|
||||
|
||||
if (svdev->scsi_dev[scsi_dev_num] == NULL) {
|
||||
scsi_dev = spdk_scsi_dev_construct(dev_name, lun_names_list, lun_id_list, 1,
|
||||
SPDK_SPC_PROTOCOL_IDENTIFIER_SAS, spdk_vhost_scsi_lun_hotremove, svdev);
|
||||
if (scsi_dev == NULL) {
|
||||
SPDK_ERRLOG("Couldn't create spdk SCSI device '%s' using lun device '%s' in controller: %s\n",
|
||||
dev_name, lun_name, vdev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
spdk_scsi_dev_add_port(svdev->scsi_dev[scsi_dev_num], 0, "vhost");
|
||||
|
||||
spdk_scsi_dev_add_port(scsi_dev, 0, "vhost");
|
||||
|
||||
if (vdev->lcore == -1) {
|
||||
svdev->detached_dev[scsi_dev_num] = false;
|
||||
svdev->scsi_dev[scsi_dev_num] = scsi_dev;
|
||||
} else {
|
||||
enqueue_vhost_event(svdev, SPDK_VHOST_SCSI_EVENT_HOTATTACH, scsi_dev_num, scsi_dev, NULL);
|
||||
}
|
||||
|
||||
SPDK_NOTICELOG("Controller %s: defined device '%s' using lun '%s'\n",
|
||||
vdev->name, dev_name, lun_name);
|
||||
return 0;
|
||||
@ -877,14 +957,14 @@ spdk_vhost_scsi_dev_remove_dev(struct spdk_vhost_dev *vdev, unsigned scsi_dev_nu
|
||||
}
|
||||
|
||||
if ((svdev->vdev.negotiated_features & (1ULL << VIRTIO_SCSI_F_HOTPLUG)) == 0) {
|
||||
SPDK_WARNLOG("Controller %s: hotremove is not supported\n", svdev->vdev.name);
|
||||
SPDK_WARNLOG("%s: 'Dev %u' is in use and hot-detach is not enabled for this controller.\n",
|
||||
svdev->vdev.name, scsi_dev_num);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
svdev->removed_dev[scsi_dev_num] = true;
|
||||
eventq_enqueue(svdev, scsi_dev, NULL, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED);
|
||||
enqueue_vhost_event(svdev, SPDK_VHOST_SCSI_EVENT_HOTDETACH, scsi_dev_num, scsi_dev, NULL);
|
||||
|
||||
SPDK_NOTICELOG("%s: 'Dev %u' marked for hotremove.\n", vdev->name, scsi_dev_num);
|
||||
SPDK_NOTICELOG("%s: queued 'Dev %u' for hot-detach.\n", vdev->name, scsi_dev_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1026,20 +1106,45 @@ alloc_task_pool(struct spdk_vhost_scsi_dev *svdev)
|
||||
static int
|
||||
new_device(int vid)
|
||||
{
|
||||
struct spdk_vhost_dev *vdev;
|
||||
struct spdk_vhost_scsi_dev *svdev = NULL;
|
||||
int rc = -1;
|
||||
|
||||
svdev = to_scsi_dev(spdk_vhost_dev_load(vid));
|
||||
vdev = spdk_vhost_dev_load(vid);
|
||||
if (vdev == NULL) {
|
||||
SPDK_ERRLOG("Trying start a controller with unknown vid: %d.\n", vid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
svdev = to_scsi_dev(vdev);
|
||||
if (svdev == NULL) {
|
||||
return -1;
|
||||
SPDK_ERRLOG("Trying to start non-scsi controller as scsi one.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (alloc_task_pool(svdev)) {
|
||||
rc = alloc_task_pool(svdev);
|
||||
if (rc != 0) {
|
||||
SPDK_ERRLOG("%s: failed to alloc task pool.", vdev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
svdev->vhost_events = spdk_ring_create(SPDK_RING_TYPE_MP_SC, 16,
|
||||
spdk_env_get_socket_id(vdev->lcore));
|
||||
if (svdev->vhost_events == NULL) {
|
||||
SPDK_ERRLOG("%s: failed to alloc event pool.", vdev->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spdk_vhost_timed_event_send(vdev->lcore, add_vdev_cb, svdev, 1, "add scsi vdev");
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
if (rc != 0) {
|
||||
spdk_vhost_dev_unload(&svdev->vdev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
spdk_vhost_timed_event_send(svdev->vdev.lcore, add_vdev_cb, svdev, 1, "add scsi vdev");
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1047,6 +1152,7 @@ destroy_device(int vid)
|
||||
{
|
||||
struct spdk_vhost_scsi_dev *svdev;
|
||||
struct spdk_vhost_dev *vdev;
|
||||
void *ev;
|
||||
struct spdk_vhost_timed_event event = {0};
|
||||
uint32_t i;
|
||||
|
||||
@ -1076,6 +1182,15 @@ destroy_device(int vid)
|
||||
|
||||
spdk_vhost_timed_event_send(vdev->lcore, remove_vdev_cb, svdev, 1, "remove scsi vdev");
|
||||
|
||||
/* Flush not sent events */
|
||||
while (spdk_ring_dequeue(svdev->vhost_events, &ev, 1) == 1) {
|
||||
/* process vhost event, but don't send virtio event */
|
||||
spdk_vhost_scsi_event_process(svdev, ev, NULL);
|
||||
spdk_dma_free(ev);
|
||||
}
|
||||
|
||||
spdk_ring_free(svdev->vhost_events);
|
||||
|
||||
free_task_pool(svdev);
|
||||
spdk_vhost_dev_unload(vdev);
|
||||
}
|
||||
|
@ -208,6 +208,26 @@ done
|
||||
$BASE_DIR/vm_run.sh $x --work-dir=$TEST_DIR $used_vms
|
||||
vm_wait_for_boot 600 $used_vms
|
||||
|
||||
if [[ $test_type == "spdk_vhost_scsi" ]]; then
|
||||
for vm_conf in ${vms[@]}; do
|
||||
IFS=',' read -ra conf <<< "$vm_conf"
|
||||
while IFS=':' read -ra disks; do
|
||||
for disk in "${disks[@]}"; do
|
||||
echo "INFO: Hotdetach test. Trying to remove existing device from a controller naa.$disk.${conf[0]}"
|
||||
$rpc_py remove_vhost_scsi_dev naa.$disk.${conf[0]} 0
|
||||
|
||||
sleep 0.1
|
||||
|
||||
echo "INFO: Hotattach test. Re-adding device 0 to naa.$disk.${conf[0]}"
|
||||
$rpc_py add_vhost_scsi_lun naa.$disk.${conf[0]} 0 $disk
|
||||
done
|
||||
done <<< "${conf[2]}"
|
||||
unset IFS;
|
||||
done
|
||||
fi
|
||||
|
||||
sleep 0.1
|
||||
|
||||
echo "==============="
|
||||
echo ""
|
||||
echo "INFO: Testing..."
|
||||
|
Loading…
Reference in New Issue
Block a user