virHostdevPCINodeDeviceReAttach;
virHostdevPCINodeDeviceReset;
virHostdevPrepareDomainDevices;
+virHostdevPrepareMediatedDevices;
virHostdevPreparePCIDevices;
virHostdevPrepareSCSIDevices;
virHostdevPrepareSCSIVHostDevices;
virHostdevPrepareUSBDevices;
virHostdevReAttachDomainDevices;
+virHostdevReAttachMediatedDevices;
virHostdevReAttachPCIDevices;
virHostdevReAttachSCSIDevices;
virHostdevReAttachSCSIVHostDevices;
virHostdevReAttachUSBDevices;
virHostdevUpdateActiveDomainDevices;
+virHostdevUpdateActiveMediatedDevices;
virHostdevUpdateActivePCIDevices;
virHostdevUpdateActiveSCSIDevices;
virHostdevUpdateActiveUSBDevices;
QEMU_DRIVER_NAME, def->name);
}
+
+int
+qemuHostdevUpdateActiveMediatedDevices(virQEMUDriverPtr driver,
+ virDomainDefPtr def)
+{
+ virHostdevManagerPtr mgr = driver->hostdevMgr;
+
+ if (!def->nhostdevs)
+ return 0;
+
+ return virHostdevUpdateActiveMediatedDevices(mgr, def->hostdevs,
+ def->nhostdevs,
+ QEMU_DRIVER_NAME, def->name);
+}
+
+
int
qemuHostdevUpdateActiveDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def)
if (qemuHostdevUpdateActiveSCSIDevices(driver, def) < 0)
return -1;
+ if (qemuHostdevUpdateActiveMediatedDevices(driver, def) < 0)
+ return -1;
+
return 0;
}
name, hostdevs, nhostdevs);
}
+int
+qemuHostdevPrepareMediatedDevices(virQEMUDriverPtr driver,
+ const char *name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+{
+ virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
+
+ if (!qemuHostdevHostSupportsPassthroughVFIO()) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("host doesn't support VFIO PCI interface"));
+ return -1;
+ }
+
+ return virHostdevPrepareMediatedDevices(hostdev_mgr, QEMU_DRIVER_NAME,
+ name, hostdevs, nhostdevs);
+}
+
int
qemuHostdevPrepareDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def,
def->hostdevs, def->nhostdevs) < 0)
return -1;
+ if (qemuHostdevPrepareMediatedDevices(driver, def->name,
+ def->hostdevs, def->nhostdevs) < 0)
+ return -1;
+
return 0;
}
name, hostdevs, nhostdevs);
}
+void
+qemuHostdevReAttachMediatedDevices(virQEMUDriverPtr driver,
+ const char *name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+{
+ virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
+
+ virHostdevReAttachMediatedDevices(hostdev_mgr, QEMU_DRIVER_NAME,
+ name, hostdevs, nhostdevs);
+}
+
void
qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def)
qemuHostdevReAttachSCSIVHostDevices(driver, def->name, def->hostdevs,
def->nhostdevs);
+
+ qemuHostdevReAttachMediatedDevices(driver, def->name, def->hostdevs,
+ def->nhostdevs);
}
bool qemuHostdevHostSupportsPassthroughLegacy(void);
bool qemuHostdevHostSupportsPassthroughVFIO(void);
+int qemuHostdevUpdateActiveMediatedDevices(virQEMUDriverPtr driver,
+ virDomainDefPtr def);
int qemuHostdevUpdateActivePCIDevices(virQEMUDriverPtr driver,
virDomainDefPtr def);
int qemuHostdevUpdateActiveUSBDevices(virQEMUDriverPtr driver,
const char *name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs);
+int qemuHostdevPrepareMediatedDevices(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 qemuHostdevReAttachMediatedDevices(virQEMUDriverPtr driver,
+ const char *name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs);
void qemuHostdevReAttachDomainDevices(virQEMUDriverPtr driver,
virDomainDefPtr def);
/* virhostdev.c: hostdev management
*
- * Copyright (C) 2006-2007, 2009-2016 Red Hat, Inc.
+ * Copyright (C) 2006-2007, 2009-2017 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
* Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
*
virObjectUnref(hostdevMgr->activeUSBHostdevs);
virObjectUnref(hostdevMgr->activeSCSIHostdevs);
virObjectUnref(hostdevMgr->activeSCSIVHostHostdevs);
+ virObjectUnref(hostdevMgr->activeMediatedHostdevs);
VIR_FREE(hostdevMgr->stateDir);
}
if (!(hostdevMgr->activeSCSIVHostHostdevs = virSCSIVHostDeviceListNew()))
goto error;
+ if (!(hostdevMgr->activeMediatedHostdevs = virMediatedDeviceListNew()))
+ goto error;
+
if (privileged) {
if (VIR_STRDUP(hostdevMgr->stateDir, HOSTDEV_STATE_DIR) < 0)
goto error;
return ret;
}
+
+int
+virHostdevUpdateActiveMediatedDevices(virHostdevManagerPtr mgr,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs,
+ const char *drv_name,
+ const char *dom_name)
+{
+ int ret = -1;
+ size_t i;
+ virMediatedDevicePtr mdev = NULL;
+
+ if (nhostdevs == 0)
+ return 0;
+
+ virObjectLock(mgr->activeMediatedHostdevs);
+ for (i = 0; i < nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = hostdevs[i];
+ virDomainHostdevSubsysMediatedDevPtr mdevsrc;
+
+ mdevsrc = &hostdev->source.subsys.u.mdev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+ hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV) {
+ continue;
+ }
+
+ if (!(mdev = virMediatedDeviceNew(mdevsrc->uuidstr, mdevsrc->model)))
+ goto cleanup;
+
+ virMediatedDeviceSetUsedBy(mdev, drv_name, dom_name);
+
+ if (virMediatedDeviceListAdd(mgr->activeMediatedHostdevs, mdev) < 0)
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ virMediatedDeviceFree(mdev);
+ virObjectUnlock(mgr->activeMediatedHostdevs);
+ return ret;
+}
+
+
static int
virHostdevMarkUSBDevices(virHostdevManagerPtr mgr,
const char *drv_name,
return -1;
}
+
+int
+virHostdevPrepareMediatedDevices(virHostdevManagerPtr mgr,
+ const char *drv_name,
+ const char *dom_name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+{
+ size_t i;
+ int ret = -1;
+ virMediatedDeviceListPtr list;
+
+ if (!nhostdevs)
+ return 0;
+
+ /* To prevent situation where mediated device is assigned to multiple
+ * domains we maintain a driver list of currently assigned mediated devices.
+ * A device is appended to the driver list after a series of preparations.
+ */
+ if (!(list = virMediatedDeviceListNew()))
+ goto cleanup;
+
+ /* Loop 1: Build a temporary list of ALL mediated devices. */
+ for (i = 0; i < nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = hostdevs[i];
+ virDomainHostdevSubsysMediatedDevPtr src = &hostdev->source.subsys.u.mdev;
+ virMediatedDevicePtr mdev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+ continue;
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV)
+ continue;
+
+ if (!(mdev = virMediatedDeviceNew(src->uuidstr, src->model)))
+ goto cleanup;
+
+ if (virMediatedDeviceListAdd(list, mdev) < 0) {
+ virMediatedDeviceFree(mdev);
+ goto cleanup;
+ }
+ }
+
+ /* Mark the devices in the list as used by @drv_name-@dom_name and copy the
+ * references to the driver list
+ */
+ if (virMediatedDeviceListMarkDevices(mgr->activeMediatedHostdevs,
+ list, drv_name, dom_name) < 0)
+ goto cleanup;
+
+ /* Loop 2: Temporary list was successfully merged with
+ * driver list, so steal all items to avoid freeing them
+ * in cleanup label.
+ */
+ while (virMediatedDeviceListCount(list) > 0) {
+ virMediatedDevicePtr tmp = virMediatedDeviceListGet(list, 0);
+ virMediatedDeviceListSteal(list, tmp);
+ }
+
+ ret = 0;
+ cleanup:
+ virObjectUnref(list);
+ return ret;
+}
+
void
virHostdevReAttachUSBDevices(virHostdevManagerPtr mgr,
const char *drv_name,
virObjectUnlock(mgr->activeSCSIVHostHostdevs);
}
+/* TODO: Rename this function along with all virHostdevReAttach* functions that
+ * have nothing to do with an explicit re-attachment of a device back to the
+ * host driver (like PCI).
+ * Despite what the function name suggests, there's nothing to be re-attached
+ * for mediated devices, the function merely removes a mediated device from the
+ * list of active host devices.
+ */
+void
+virHostdevReAttachMediatedDevices(virHostdevManagerPtr mgr,
+ const char *drv_name,
+ const char *dom_name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+{
+ const char *used_by_drvname = NULL;
+ const char *used_by_domname = NULL;
+ size_t i;
+
+ if (nhostdevs == 0)
+ return;
+
+ virObjectLock(mgr->activeMediatedHostdevs);
+ for (i = 0; i < nhostdevs; i++) {
+ virMediatedDevicePtr mdev, tmp;
+ virDomainHostdevSubsysMediatedDevPtr mdevsrc;
+ virDomainHostdevDefPtr hostdev = hostdevs[i];
+
+ mdevsrc = &hostdev->source.subsys.u.mdev;
+
+ if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+ hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV) {
+ continue;
+ }
+
+ if (!(mdev = virMediatedDeviceNew(mdevsrc->uuidstr,
+ mdevsrc->model)))
+ continue;
+
+ /* Remove from the list only mdevs assigned to @drv_name/@dom_name */
+
+ tmp = virMediatedDeviceListFind(mgr->activeMediatedHostdevs, mdev);
+ virMediatedDeviceFree(mdev);
+
+ /* skip inactive devices */
+ if (!tmp)
+ continue;
+
+ virMediatedDeviceGetUsedBy(tmp, &used_by_drvname, &used_by_domname);
+ if (STREQ_NULLABLE(drv_name, used_by_drvname) &&
+ STREQ_NULLABLE(dom_name, used_by_domname)) {
+ VIR_DEBUG("Removing %s dom=%s from activeMediatedHostdevs",
+ mdevsrc->uuidstr, dom_name);
+ virMediatedDeviceListDel(mgr->activeMediatedHostdevs, tmp);
+ }
+ }
+ virObjectUnlock(mgr->activeMediatedHostdevs);
+}
+
int
virHostdevPCINodeDeviceDetach(virHostdevManagerPtr mgr,
virPCIDevicePtr pci)
# include "virscsi.h"
# include "virscsivhost.h"
# include "conf/domain_conf.h"
+# include "virmdev.h"
typedef enum {
VIR_HOSTDEV_STRICT_ACS_CHECK = (1 << 0), /* strict acs check */
virUSBDeviceListPtr activeUSBHostdevs;
virSCSIDeviceListPtr activeSCSIHostdevs;
virSCSIVHostDeviceListPtr activeSCSIVHostHostdevs;
+ virMediatedDeviceListPtr activeMediatedHostdevs;
};
virHostdevManagerPtr virHostdevManagerGetDefault(void);
virDomainHostdevDefPtr *hostdevs,
int nhostdevs)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+int
+virHostdevPrepareMediatedDevices(virHostdevManagerPtr hostdev_mgr,
+ const char *drv_name,
+ const char *dom_name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
void
virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
const char *drv_name,
virDomainHostdevDefPtr *hostdevs,
int nhostdevs)
ATTRIBUTE_NONNULL(1);
+void
+virHostdevReAttachMediatedDevices(virHostdevManagerPtr hostdev_mgr,
+ const char *drv_name,
+ const char *dom_name,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
int
virHostdevUpdateActivePCIDevices(virHostdevManagerPtr mgr,
virDomainHostdevDefPtr *hostdevs,
const char *dom_name)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
int
+virHostdevUpdateActiveMediatedDevices(virHostdevManagerPtr mgr,
+ virDomainHostdevDefPtr *hostdevs,
+ int nhostdevs,
+ const char *drv_name,
+ const char *dom_name)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
+int
virHostdevUpdateActiveDomainDevices(virHostdevManagerPtr mgr,
const char *driver,
virDomainDefPtr def,