mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-23 04:55:18 +00:00
qemu: Add vhost-scsi string for -device parameter
Open /dev/vhost-scsi, and record the resulting file descriptor, so that the guest has access to the host device outside of the libvirt daemon. Pass this information, along with data parsed from the XML file, to build a device string for the qemu command line. That device string will be for either a vhost-scsi-ccw device in the case of an s390 machine, or vhost-scsi-pci for any others. Signed-off-by: Eric Farman <farman@linux.vnet.ibm.com>
This commit is contained in:
parent
629544be0f
commit
9cc26dc622
@ -299,6 +299,25 @@ qemuSetupHostSCSIDeviceCgroup(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuSetupHostSCSIVHostDeviceCgroup(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED,
|
||||||
|
const char *path,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
virDomainObjPtr vm = opaque;
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
VIR_DEBUG("Process path '%s' for scsi_host device", path);
|
||||||
|
|
||||||
|
ret = virCgroupAllowDevicePath(priv->cgroup, path,
|
||||||
|
VIR_CGROUP_DEVICE_RW, false);
|
||||||
|
|
||||||
|
virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path, "rw", ret == 0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuSetupHostdevCgroup(virDomainObjPtr vm,
|
qemuSetupHostdevCgroup(virDomainObjPtr vm,
|
||||||
virDomainHostdevDefPtr dev)
|
virDomainHostdevDefPtr dev)
|
||||||
@ -308,9 +327,11 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm,
|
|||||||
virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
|
virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
|
||||||
virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
|
virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
|
||||||
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
|
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
|
||||||
|
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
|
||||||
virPCIDevicePtr pci = NULL;
|
virPCIDevicePtr pci = NULL;
|
||||||
virUSBDevicePtr usb = NULL;
|
virUSBDevicePtr usb = NULL;
|
||||||
virSCSIDevicePtr scsi = NULL;
|
virSCSIDevicePtr scsi = NULL;
|
||||||
|
virSCSIVHostDevicePtr host = NULL;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
|
||||||
/* currently this only does something for PCI devices using vfio
|
/* currently this only does something for PCI devices using vfio
|
||||||
@ -399,6 +420,16 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: {
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: {
|
||||||
|
if (hostsrc->protocol ==
|
||||||
|
VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) {
|
||||||
|
if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virSCSIVHostDeviceFileIterate(host,
|
||||||
|
qemuSetupHostSCSIVHostDeviceCgroup,
|
||||||
|
vm) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,6 +443,7 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm,
|
|||||||
virPCIDeviceFree(pci);
|
virPCIDeviceFree(pci);
|
||||||
virUSBDeviceFree(usb);
|
virUSBDeviceFree(usb);
|
||||||
virSCSIDeviceFree(scsi);
|
virSCSIDeviceFree(scsi);
|
||||||
|
virSCSIVHostDeviceFree(host);
|
||||||
VIR_FREE(path);
|
VIR_FREE(path);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -4741,6 +4741,44 @@ qemuBuildSCSIiSCSIHostdevDrvStr(virDomainHostdevDefPtr dev)
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def,
|
||||||
|
virDomainHostdevDefPtr dev,
|
||||||
|
virQEMUCapsPtr qemuCaps,
|
||||||
|
char *vhostfdName)
|
||||||
|
{
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
|
||||||
|
|
||||||
|
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_SCSI)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("This QEMU doesn't support vhost-scsi devices"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ARCH_IS_S390(def->os.arch))
|
||||||
|
virBufferAddLit(&buf, "vhost-scsi-ccw");
|
||||||
|
else
|
||||||
|
virBufferAddLit(&buf, "vhost-scsi-pci");
|
||||||
|
|
||||||
|
virBufferAsprintf(&buf, ",wwpn=%s,vhostfd=%s,id=%s",
|
||||||
|
hostsrc->wwpn,
|
||||||
|
vhostfdName,
|
||||||
|
dev->info->alias);
|
||||||
|
|
||||||
|
if (qemuBuildDeviceAddressStr(&buf, def, dev->info, qemuCaps) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virBufferCheckError(&buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
return virBufferContentAndReset(&buf);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virBufferFreeAndReset(&buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev)
|
qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev)
|
||||||
{
|
{
|
||||||
@ -5221,6 +5259,48 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SCSI_host */
|
||||||
|
if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
||||||
|
subsys->type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
|
||||||
|
if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("SCSI passthrough is not supported by this "
|
||||||
|
"version of qemu"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostdev->source.subsys.u.scsi_host.protocol ==
|
||||||
|
VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST) {
|
||||||
|
char *vhostfdName = NULL;
|
||||||
|
int vhostfd = -1;
|
||||||
|
|
||||||
|
if (virSCSIVHostOpenVhostSCSI(&vhostfd) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (virAsprintf(&vhostfdName, "%d", vhostfd) < 0) {
|
||||||
|
VIR_FORCE_CLOSE(vhostfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virCommandPassFD(cmd, vhostfd,
|
||||||
|
VIR_COMMAND_PASS_FD_CLOSE_PARENT);
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "-device");
|
||||||
|
if (!(devstr = qemuBuildSCSIVHostHostdevDevStr(def,
|
||||||
|
hostdev,
|
||||||
|
qemuCaps,
|
||||||
|
vhostfdName))) {
|
||||||
|
VIR_FREE(vhostfdName);
|
||||||
|
VIR_FORCE_CLOSE(vhostfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
virCommandAddArg(cmd, devstr);
|
||||||
|
|
||||||
|
VIR_FREE(vhostfdName);
|
||||||
|
VIR_FREE(devstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -164,6 +164,11 @@ char *qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev);
|
|||||||
char *qemuBuildSCSIHostdevDevStr(const virDomainDef *def,
|
char *qemuBuildSCSIHostdevDevStr(const virDomainDef *def,
|
||||||
virDomainHostdevDefPtr dev,
|
virDomainHostdevDefPtr dev,
|
||||||
virQEMUCapsPtr qemuCaps);
|
virQEMUCapsPtr qemuCaps);
|
||||||
|
char *
|
||||||
|
qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def,
|
||||||
|
virDomainHostdevDefPtr dev,
|
||||||
|
virQEMUCapsPtr qemuCaps,
|
||||||
|
char *vhostfdName);
|
||||||
|
|
||||||
char *qemuBuildRedirdevDevStr(const virDomainDef *def,
|
char *qemuBuildRedirdevDevStr(const virDomainDef *def,
|
||||||
virDomainRedirdevDefPtr dev,
|
virDomainRedirdevDefPtr dev,
|
||||||
|
@ -312,6 +312,14 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < def->nhostdevs; i++) {
|
||||||
|
if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
|
||||||
|
def->hostdevs[i]->source.subsys.type ==
|
||||||
|
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST &&
|
||||||
|
def->hostdevs[i]->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
||||||
|
def->hostdevs[i]->info->type = type;
|
||||||
|
}
|
||||||
|
|
||||||
if (def->memballoon &&
|
if (def->memballoon &&
|
||||||
def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
|
def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
|
||||||
def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
||||||
@ -1594,8 +1602,10 @@ qemuDomainAssignDevicePCISlots(virDomainDefPtr def,
|
|||||||
for (i = 0; i < def->nhostdevs; i++) {
|
for (i = 0; i < def->nhostdevs; i++) {
|
||||||
if (!virDeviceInfoPCIAddressWanted(def->hostdevs[i]->info))
|
if (!virDeviceInfoPCIAddressWanted(def->hostdevs[i]->info))
|
||||||
continue;
|
continue;
|
||||||
if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
|
if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
||||||
def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
|
continue;
|
||||||
|
if (def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
|
||||||
|
def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (qemuDomainPCIAddressReserveNextSlot(addrs,
|
if (qemuDomainPCIAddressReserveNextSlot(addrs,
|
||||||
|
@ -292,6 +292,17 @@ qemuHostdevPrepareSCSIDevices(virQEMUDriverPtr driver,
|
|||||||
name, hostdevs, nhostdevs);
|
name, hostdevs, nhostdevs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuHostdevPrepareSCSIVHostDevices(virQEMUDriverPtr driver,
|
||||||
|
const char *name,
|
||||||
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
|
int nhostdevs)
|
||||||
|
{
|
||||||
|
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
||||||
|
|
||||||
|
return virHostdevPrepareSCSIVHostDevices(hostdev_mgr, QEMU_DRIVER_NAME,
|
||||||
|
name, hostdevs, nhostdevs);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
|
qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
|
||||||
@ -315,6 +326,10 @@ qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
|
|||||||
def->hostdevs, def->nhostdevs) < 0)
|
def->hostdevs, def->nhostdevs) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (qemuHostdevPrepareSCSIVHostDevices(driver, def->name,
|
||||||
|
def->hostdevs, def->nhostdevs) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,6 +384,18 @@ qemuHostdevReAttachSCSIDevices(virQEMUDriverPtr driver,
|
|||||||
name, hostdevs, nhostdevs);
|
name, hostdevs, nhostdevs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver,
|
||||||
|
const char *name,
|
||||||
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
|
int nhostdevs)
|
||||||
|
{
|
||||||
|
virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
|
||||||
|
|
||||||
|
virHostdevReAttachSCSIVHostDevices(hostdev_mgr, QEMU_DRIVER_NAME,
|
||||||
|
name, hostdevs, nhostdevs);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
|
qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
|
||||||
virDomainDefPtr def)
|
virDomainDefPtr def)
|
||||||
@ -384,4 +411,7 @@ qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
|
|||||||
|
|
||||||
qemuHostdevReAttachSCSIDevices(driver, def->name, def->hostdevs,
|
qemuHostdevReAttachSCSIDevices(driver, def->name, def->hostdevs,
|
||||||
def->nhostdevs);
|
def->nhostdevs);
|
||||||
|
|
||||||
|
qemuHostdevReAttachSCSIVHostDevices(driver, def->name, def->hostdevs,
|
||||||
|
def->nhostdevs);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,10 @@ int qemuHostdevPrepareSCSIDevices(virQEMUDriverPtr driver,
|
|||||||
const char *name,
|
const char *name,
|
||||||
virDomainHostdevDefPtr *hostdevs,
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
int nhostdevs);
|
int nhostdevs);
|
||||||
|
int qemuHostdevPrepareSCSIVHostDevices(virQEMUDriverPtr driver,
|
||||||
|
const char *name,
|
||||||
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
|
int nhostdevs);
|
||||||
int qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
|
int qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
|
||||||
virDomainDefPtr def,
|
virDomainDefPtr def,
|
||||||
virQEMUCapsPtr qemuCaps,
|
virQEMUCapsPtr qemuCaps,
|
||||||
@ -72,6 +76,10 @@ void qemuHostdevReAttachSCSIDevices(virQEMUDriverPtr driver,
|
|||||||
const char *name,
|
const char *name,
|
||||||
virDomainHostdevDefPtr *hostdevs,
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
int nhostdevs);
|
int nhostdevs);
|
||||||
|
void qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver,
|
||||||
|
const char *name,
|
||||||
|
virDomainHostdevDefPtr *hostdevs,
|
||||||
|
int nhostdevs);
|
||||||
void qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
|
void qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
|
||||||
virDomainDefPtr def);
|
virDomainDefPtr def);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user