From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch adds support for device_add hotplug for vhost-scsi-pci against QEMU >= v1.5.x code. This includes: - Add qemuOpenVhostSCSI() to open fds to /dev/vhost-scsi character device. - Changes to qemuBuildControllerDevStr() for adding 'vhostfd=' parameters to device_add. - Add qemuMonitorAddControllerVhost() that is specific to VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VHOST_SCSI - Update qemuDomainAttachControllerDevice() to setup vhostfd fd + name arrays, and invoke qemuOpenVhostSCSI(). - Update qemuDomainAttachControllerDevice() to invoke qemuMonitorAddControllerVhost() -> qemuMonitorSendFileHandle() -> qemuMonitorAddDevice() in order to pass the pre-opened vhostfd. This code has been tested using openstack nova volume-attach, using a Juno v2 development head from 07192014. Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> Signed-off-by: Mike Perez <thingee@xxxxxxxxx> --- src/qemu/qemu_command.c | 56 ++++++++++++++++++++++++++++++++++++++++++++--- src/qemu/qemu_command.h | 8 ++++++- src/qemu/qemu_hotplug.c | 47 +++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_monitor.c | 24 ++++++++++++++++++++ src/qemu/qemu_monitor.h | 4 ++++ 5 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 43c0e1c..1e987f9 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -678,6 +678,38 @@ static int qemuAssignDeviceDiskAliasFixed(virDomainDiskDefPtr disk) return 0; } +int +qemuOpenVhostSCSI(virDomainControllerDefPtr controller, + int *vhostfd, + int *vhostfdSize) +{ + size_t i; + + if (controller->model != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VHOST_SCSI) { + *vhostfdSize = 0; + return 0; + } + + for (i = 0; i < *vhostfdSize; i++) { + vhostfd[i] = open("/dev/vhost-scsi", O_RDWR); + + if (vhostfd[i] < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("vhost-scsi was requested for an interface, " + "but is unavailable")); + goto error; + } + } + + return 0; + + error: + while (i--) + VIR_FORCE_CLOSE(vhostfd[i]); + + return -1; +} + static int qemuSetSCSIControllerModel(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, @@ -4153,10 +4185,13 @@ char * qemuBuildControllerDevStr(virDomainDefPtr domainDef, virDomainControllerDefPtr def, virQEMUCapsPtr qemuCaps, - int *nusbcontroller) + int *nusbcontroller, + char **vhostfd, + int vhostfdSize) { virBuffer buf = VIR_BUFFER_INITIALIZER; int model; + size_t i; if (!(def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI && (def->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI || @@ -4328,6 +4363,19 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, if (def->wwpn) virBufferAsprintf(&buf, ",wwpn=%s", def->wwpn); + if (vhostfdSize) { + if (vhostfdSize == 1) { + virBufferAsprintf(&buf, ",vhostfd=%s", vhostfd[0]); + } else { + virBufferAddLit(&buf, ",vhostfds="); + for (i = 0; i < vhostfdSize; i++) { + if (i) + virBufferAddChar(&buf, ':'); + virBufferAdd(&buf, vhostfd[i], -1); + } + } + } + if (qemuBuildDeviceAddressStr(&buf, domainDef, &def->info, qemuCaps) < 0) goto error; @@ -7843,7 +7891,8 @@ qemuBuildCommandLine(virConnectPtr conn, virCommandAddArg(cmd, "-device"); if (!(devstr = qemuBuildControllerDevStr(def, cont, - qemuCaps, NULL))) + qemuCaps, NULL, + NULL, 0))) goto error; virCommandAddArg(cmd, devstr); @@ -7867,7 +7916,8 @@ qemuBuildCommandLine(virConnectPtr conn, char *devstr; if (!(devstr = qemuBuildControllerDevStr(def, cont, qemuCaps, - &usbcontroller))) + &usbcontroller, NULL, + 0))) goto error; virCommandAddArg(cmd, devstr); diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index cf51056..b0651ff 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -114,6 +114,10 @@ char * qemuBuildNicDevStr(virDomainDefPtr def, char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk, virQEMUCapsPtr qemuCaps); +int qemuOpenVhostSCSI(virDomainControllerDefPtr controller, + int *vhostfd, + int *vhostfdSize); + /* Both legacy & current support */ char *qemuBuildDriveStr(virConnectPtr conn, virDomainDiskDefPtr disk, @@ -134,7 +138,9 @@ char * qemuBuildFSDevStr(virDomainDefPtr domainDef, char * qemuBuildControllerDevStr(virDomainDefPtr domainDef, virDomainControllerDefPtr def, virQEMUCapsPtr qemuCaps, - int *nusbcontroller); + int *nusbcontroller, + char **vhostfd, + int vhostfdSize); char * qemuBuildWatchdogDevStr(virDomainDefPtr domainDef, virDomainWatchdogDefPtr dev, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 1fc28b8..4cdac56 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -360,9 +360,13 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainControllerDefPtr controller) { + size_t i; int ret = -1; const char* type = virDomainControllerTypeToString(controller->type); char *devstr = NULL; + char **vhostfdName = NULL; + int *vhostfd = NULL; + int vhostfdSize = 0; qemuDomainObjPrivatePtr priv = vm->privateData; bool releaseaddr = false; @@ -403,7 +407,30 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, goto cleanup; } - if (!(devstr = qemuBuildControllerDevStr(vm->def, controller, priv->qemuCaps, NULL))) { + if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VHOST_SCSI) { + /* FIXME: Get total number of virtio-scsi queues */ + vhostfdSize = 1; + + if (VIR_ALLOC_N(vhostfd, vhostfdSize) < 0) + goto cleanup; + + memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize); + + if (VIR_ALLOC_N(vhostfdName, vhostfdSize) < 0) + goto cleanup; + + if (qemuOpenVhostSCSI(controller, vhostfd, &vhostfdSize) < 0) + goto cleanup; + + for (i = 0; i < vhostfdSize; i++) { + if (virAsprintf(&vhostfdName[i], "vhostfd-%s%zu", + controller->info.alias, i) < 0) + goto cleanup; + } + } + + if (!(devstr = qemuBuildControllerDevStr(vm->def, controller, priv->qemuCaps, + NULL, vhostfdName, vhostfdSize))) { goto cleanup; } } @@ -413,7 +440,12 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, qemuDomainObjEnterMonitor(driver, vm); if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { - ret = qemuMonitorAddDevice(priv->mon, devstr); + if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VHOST_SCSI) { + ret = qemuMonitorAddControllerVhost(priv->mon, devstr, + vhostfd, vhostfdName, vhostfdSize); + } else { + ret = qemuMonitorAddDevice(priv->mon, devstr); + } } else { ret = qemuMonitorAttachPCIDiskController(priv->mon, type, @@ -421,6 +453,9 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, } qemuDomainObjExitMonitor(driver, vm); + for (i = 0; i < vhostfdSize; i++) + VIR_FORCE_CLOSE(vhostfd[i]); + if (ret == 0) { if (controller->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -431,6 +466,14 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver, if (ret != 0 && releaseaddr) qemuDomainReleaseDeviceAddress(vm, &controller->info, NULL); + for (i = 0; vhostfd && i < vhostfdSize; i++) { + VIR_FORCE_CLOSE(vhostfd[i]); + if (vhostfdName) + VIR_FREE(vhostfdName[i]); + } + VIR_FREE(vhostfd); + VIR_FREE(vhostfdName); + VIR_FREE(devstr); return ret; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index db3dd73..3e67c85 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3052,6 +3052,30 @@ int qemuMonitorAddDevice(qemuMonitorPtr mon, return qemuMonitorAddDeviceWithFd(mon, devicestr, -1, NULL); } +int qemuMonitorAddControllerVhost(qemuMonitorPtr mon, + const char *devicestr, + int *vhostfd, char **vhostfdName, int vhostfdSize) +{ + size_t i = 0; + + for (i = 0; i < vhostfdSize; i++) { + if (qemuMonitorSendFileHandle(mon, vhostfdName[i], vhostfd[i]) < 0) + goto cleanup; + } + + if (qemuMonitorAddDevice(mon, devicestr) < 0) + goto cleanup; + + return 0; + + cleanup: + while (i--) { + if (qemuMonitorCloseFileHandle(mon, vhostfdName[i]) < 0) + VIR_WARN("failed to close device handle '%s'", vhostfdName[i]); + } + return -1; +} + int qemuMonitorAddDrive(qemuMonitorPtr mon, const char *drivestr) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 8a23267..8fe21a0 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -620,6 +620,10 @@ int qemuMonitorAddDeviceWithFd(qemuMonitorPtr mon, int fd, const char *fdname); +int qemuMonitorAddControllerVhost(qemuMonitorPtr mon, + const char *devicestr, + int *vhostfd, char **vhostfdName, int vhostfdSize); + int qemuMonitorDelDevice(qemuMonitorPtr mon, const char *devalias); -- 1.7.9.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list