[libvirt] [PATCH v4 5/9] qemu: Allow hotplug of vhost-scsi device

John Ferlan jferlan at redhat.com
Tue Nov 22 21:11:38 UTC 2016



On 11/21/2016 10:58 PM, Eric Farman wrote:
> Adjust the device string that is built for vhost-scsi devices so that it
> can be invoked from hotplug.
> 
> From the QEMU command line, the file descriptors are expect to be numeric only.
> However, for hotplug, the file descriptors are expected to begin with at least
> one alphabetic character else this error occurs:
> 
>   # virsh attach-device guest_0001 ~/vhost.xml
>   error: Failed to attach device from /root/vhost.xml
>   error: internal error: unable to execute QEMU command 'getfd':
>   Parameter 'fdname' expects a name not starting with a digit
> 
> We also close the file descriptor in this case, so that shutting down the
> guest cleans up the host cgroup entries and allows future guests to use
> vhost-scsi devices.  (Otherwise the guest will silently end.)
> 
> Signed-off-by: Eric Farman <farman at linux.vnet.ibm.com>
> ---
>  src/qemu/qemu_hotplug.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 164 insertions(+)
> 
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index 0508c67..02e248f 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -2443,6 +2443,126 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
>      goto cleanup;
>  }
>  
> +static int
> +qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver,
> +                                virDomainObjPtr vm,
> +                                virDomainHostdevDefPtr hostdev)
> +{
> +    int ret = -1;
> +    qemuDomainObjPrivatePtr priv = vm->privateData;
> +    virErrorPtr orig_err;
> +    virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_HOSTDEV,
> +                               { .hostdev = hostdev } };
> +    virDomainCCWAddressSetPtr ccwaddrs = NULL;
> +    char *vhostfdName = NULL;
> +    int vhostfd = -1;
> +    char *devstr = NULL;
> +    bool teardowncgroup = false;
> +    bool teardownlabel = false;
> +    bool releaseaddr = false;
> +
> +    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("SCSI passthrough is not supported by this version of qemu"));
> +        goto cleanup;
> +    }
> +
> +    if (qemuHostdevPrepareSCSIVHostDevices(driver, vm->def->name, &hostdev, 1) < 0) {
> +        virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host;
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       _("Unable to prepare scsi_host hostdev: %s"),
> +                       hostsrc->wwpn);
> +        goto cleanup;
> +    }
> +
> +    if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
> +        goto cleanup;
> +    teardowncgroup = true;
> +
> +    if (virSecurityManagerSetHostdevLabel(driver->securityManager,
> +                                          vm->def, hostdev, NULL) < 0)
> +        goto cleanup;
> +    teardownlabel = true;
> +
> +    if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0)
> +        goto cleanup;
> +
> +    if (virAsprintf(&vhostfdName, "vhostfd-%d", vhostfd) < 0)
> +        goto cleanup;
> +
> +    if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
> +        if (qemuDomainMachineIsS390CCW(vm->def) &&
> +            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW))
> +            hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
> +    }
> +
> +    if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
> +        hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
> +        if (qemuDomainEnsurePCIAddress(vm, &dev) < 0)
> +            goto cleanup;
> +    } else if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
> +        if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
> +            goto cleanup;
> +        if (virDomainCCWAddressAssign(hostdev->info, ccwaddrs,
> +                                      !hostdev->info->addr.ccw.assigned) < 0)
> +            goto cleanup;
> +    }
> +    releaseaddr = true;
> +
> +    if (qemuAssignDeviceHostdevAlias(vm->def, &hostdev->info->alias, -1) < 0)
> +        goto cleanup;
> +
> +    if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(vm->def,
> +                                                   hostdev,
> +                                                   priv->qemuCaps,
> +                                                   vhostfdName)))
> +        goto cleanup;
> +
> +    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
> +        goto cleanup;
> +
> +    qemuDomainObjEnterMonitor(driver, vm);
> +
> +    if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd, vhostfdName) < 0)
> +        goto exit_monitor;
> +
> +    if (qemuDomainObjExitMonitor(driver, vm) < 0)
> +        goto audit;
> +
> +    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
> +    ret = 0;
> +
> + audit:
> +    virDomainAuditHostdev(vm, hostdev, "attach", (ret == 0));
> +
> + cleanup:
> +    virDomainCCWAddressSetFree(ccwaddrs);


Similar to AttachHost{PCI|USB|SCSI}Devices since
qemuHostdevPrepareSCSIVHostDevices was called, we need to call
virHostdevReAttachSCSIVHostDevices when ret < 0

I will adjust before pushing - most likely will follow PCI or USB (it's
been a long term goal to make them all consistent).

ACK -

John

[...]




More information about the libvir-list mailing list