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
qemuSetupHostdevCgroup(virDomainObjPtr vm,
virDomainHostdevDefPtr dev)
virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
+ virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
virPCIDevicePtr pci = NULL;
virUSBDevicePtr usb = NULL;
virSCSIDevicePtr scsi = NULL;
+ virSCSIVHostDevicePtr host = NULL;
char *path = NULL;
/* currently this only does something for PCI devices using vfio
}
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;
}
virPCIDeviceFree(pci);
virUSBDeviceFree(usb);
virSCSIDeviceFree(scsi);
+ virSCSIVHostDeviceFree(host);
VIR_FREE(path);
return ret;
}
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 *
qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev)
{
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;
char *qemuBuildSCSIHostdevDevStr(const virDomainDef *def,
virDomainHostdevDefPtr dev,
virQEMUCapsPtr qemuCaps);
+char *
+qemuBuildSCSIVHostHostdevDevStr(const virDomainDef *def,
+ virDomainHostdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps,
+ char *vhostfdName);
char *qemuBuildRedirdevDevStr(const virDomainDef *def,
virDomainRedirdevDefPtr dev,
}
}
+ 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 &&
def->memballoon->model == VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO &&
def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
for (i = 0; i < def->nhostdevs; i++) {
if (!virDeviceInfoPCIAddressWanted(def->hostdevs[i]->info))
continue;
- if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
- def->hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ 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;
if (qemuDomainPCIAddressReserveNextSlot(addrs,
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
qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
def->hostdevs, def->nhostdevs) < 0)
return -1;
+ if (qemuHostdevPrepareSCSIVHostDevices(driver, def->name,
+ def->hostdevs, def->nhostdevs) < 0)
+ return -1;
+
return 0;
}
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
qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def)
qemuHostdevReAttachSCSIDevices(driver, def->name, def->hostdevs,
def->nhostdevs);
+
+ qemuHostdevReAttachSCSIVHostDevices(driver, def->name, def->hostdevs,
+ def->nhostdevs);
}
const char *name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs);
+int qemuHostdevPrepareSCSIVHostDevices(virQEMUDriverPtr driver,
+ const char *name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs);
int qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def,
virQEMUCapsPtr qemuCaps,
const char *name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs);
+void qemuHostdevReAttachSCSIVHostDevices(virQEMUDriverPtr driver,
+ const char *name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs);
void qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def);