From nobody Mon Feb 9 10:37:20 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.37 as permitted sender) client-ip=209.132.183.37; envelope-from=libvir-list-bounces@redhat.com; helo=mx5-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.37 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx5-phx2.redhat.com (mx5-phx2.redhat.com [209.132.183.37]) by mx.zohomail.com with SMTPS id 1487194633822248.15988087448818; Wed, 15 Feb 2017 13:37:13 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx5-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1FLXHID004826; Wed, 15 Feb 2017 16:33:17 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1FLX17B004729 for ; Wed, 15 Feb 2017 16:33:01 -0500 Received: from beluga.usersys.redhat.com (dhcp129-94.brq.redhat.com [10.34.129.94]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1FLWmic021192; Wed, 15 Feb 2017 16:33:00 -0500 From: Erik Skultety To: libvir-list@redhat.com Date: Wed, 15 Feb 2017 22:32:28 +0100 Message-Id: <040d35f433aaf56b068b88c645995939c88409be.1487193773.git.eskultet@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-loop: libvir-list@redhat.com Cc: Erik Skultety Subject: [libvirt] [RFC PATCH v2 11/18] hostdev: Maintain a driver list of active mediated devices X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Keep track of the assigned mediated devices the same way we do it for the rest of hostdevs. Signed-off-by: Erik Skultety --- src/libvirt_private.syms | 1 + src/qemu/qemu_hostdev.c | 22 ++++++ src/qemu/qemu_hostdev.h | 4 ++ src/util/virhostdev.c | 176 +++++++++++++++++++++++++++++++++++++++++++= +++- src/util/virhostdev.h | 9 +++ 5 files changed, 211 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 48c86a2..97f81ee 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1709,6 +1709,7 @@ virHostdevPCINodeDeviceDetach; virHostdevPCINodeDeviceReAttach; virHostdevPCINodeDeviceReset; virHostdevPrepareDomainDevices; +virHostdevPrepareMediatedDevices; virHostdevPreparePCIDevices; virHostdevPrepareSCSIDevices; virHostdevPrepareSCSIVHostDevices; diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c index 7cd49e4..45b731c 100644 --- a/src/qemu/qemu_hostdev.c +++ b/src/qemu/qemu_hostdev.c @@ -305,6 +305,24 @@ qemuHostdevPrepareSCSIVHostDevices(virQEMUDriverPtr dr= iver, } =20 int +qemuHostdevPrepareMediatedDevices(virQEMUDriverPtr driver, + const char *name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + virHostdevManagerPtr hostdev_mgr =3D 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, virQEMUCapsPtr qemuCaps, @@ -330,6 +348,10 @@ qemuHostdevPrepareDomainDevices(virQEMUDriverPtr drive= r, def->hostdevs, def->nhostdevs) = < 0) return -1; =20 + if (qemuHostdevPrepareMediatedDevices(driver, def->name, + def->hostdevs, def->nhostdevs) <= 0) + return -1; + return 0; } =20 diff --git a/src/qemu/qemu_hostdev.h b/src/qemu/qemu_hostdev.h index 74a7d4f..9399241 100644 --- a/src/qemu/qemu_hostdev.h +++ b/src/qemu/qemu_hostdev.h @@ -59,6 +59,10 @@ int qemuHostdevPrepareSCSIVHostDevices(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, diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 86ca8e0..681f720 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -1,6 +1,6 @@ /* 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. * @@ -147,6 +147,7 @@ virHostdevManagerDispose(void *obj) virObjectUnref(hostdevMgr->activeUSBHostdevs); virObjectUnref(hostdevMgr->activeSCSIHostdevs); virObjectUnref(hostdevMgr->activeSCSIVHostHostdevs); + virObjectUnref(hostdevMgr->activeMediatedHostdevs); VIR_FREE(hostdevMgr->stateDir); } =20 @@ -174,6 +175,9 @@ virHostdevManagerNew(void) if (!(hostdevMgr->activeSCSIVHostHostdevs =3D virSCSIVHostDeviceListNe= w())) goto error; =20 + if (!(hostdevMgr->activeMediatedHostdevs =3D virMediatedDeviceListNew(= ))) + goto error; + if (privileged) { if (VIR_STRDUP(hostdevMgr->stateDir, HOSTDEV_STATE_DIR) < 0) goto error; @@ -1595,6 +1599,176 @@ virHostdevPrepareSCSIVHostDevices(virHostdevManager= Ptr mgr, return -1; } =20 + +static bool +virHostdevMediatedDeviceIsUsed(virMediatedDevicePtr dev, + virMediatedDeviceListPtr list) +{ + const char *drvname, *domname; + virMediatedDevicePtr tmp =3D NULL; + + virObjectLock(list); + + if ((tmp =3D virMediatedDeviceListFind(list, dev))) { + virMediatedDeviceGetUsedBy(tmp, &drvname, &domname); + virReportError(VIR_ERR_OPERATION_INVALID, + _("Mediated device %s is in use by " + "driver %s, domain %s"), + virMediatedDeviceGetPath(tmp), + drvname, domname); + } + + virObjectUnlock(list); + return !!tmp; +} + + +static int +virHostdevMediatedDeviceCheckModel(virMediatedDevicePtr dev, + virMediatedDeviceModelType model) +{ + int ret =3D -1; + char *dev_api =3D NULL; + int actual_model; + + if (virMediatedDeviceGetDeviceAPI(dev, &dev_api) < 0) + return -1; + + /* safeguard in case we've got an older libvirt which doesn't know new= er + * device_api models yet + */ + if ((actual_model =3D virMediatedDeviceModelTypeFromString(dev_api)) <= =3D 0) + goto cleanup; + + if (actual_model !=3D model) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid device API '%s' for device %s: " + "device only supports '%s'"), + virMediatedDeviceModelTypeToString(model), + virMediatedDeviceGetPath(dev), dev_api); + goto cleanup; + } + + ret =3D 0; + cleanup: + VIR_FREE(dev_api); + return ret; +} + + +static int +virHostdevMarkMediatedDevices(virHostdevManagerPtr mgr, + const char *drvname, + const char *domname, + virMediatedDeviceListPtr list) +{ + int ret =3D -1; + size_t i, j, count; + + virObjectLock(mgr->activeMediatedHostdevs); + + count =3D virMediatedDeviceListCount(list); + for (i =3D 0; i < count; i++) { + virMediatedDevicePtr mdev =3D virMediatedDeviceListGet(list, i); + VIR_DEBUG("Adding %s to activeMediatedHostdevs", + virMediatedDeviceGetPath(mdev)); + + virMediatedDeviceSetUsedBy(mdev, drvname, domname); + + /* Copy mdev references to the driver list: + * - caller is responsible for NOT freeing devices in @list on suc= cess + * - we're responsible for performing a rollback on failure + */ + if (virMediatedDeviceListAdd(mgr->activeMediatedHostdevs, mdev) < = 0) + goto rollback; + } + + ret =3D 0; + cleanup: + virObjectUnlock(mgr->activeMediatedHostdevs); + return ret; + + rollback: + for (j =3D 0; j < i; j++) { + virMediatedDevicePtr tmp =3D virMediatedDeviceListGet(list, j); + virMediatedDeviceListSteal(mgr->activeMediatedHostdevs, tmp); + } + goto cleanup; +} + + +int +virHostdevPrepareMediatedDevices(virHostdevManagerPtr mgr, + const char *drv_name, + const char *dom_name, + virDomainHostdevDefPtr *hostdevs, + int nhostdevs) +{ + size_t i; + int ret =3D -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 de= vices. + * A device is appended to the driver list after a series of preparati= ons. + */ + if (!(list =3D virMediatedDeviceListNew())) + goto cleanup; + + /* Loop 1: Build a temporary list of unused mediated devices. */ + for (i =3D 0; i < nhostdevs; i++) { + virDomainHostdevDefPtr hostdev =3D hostdevs[i]; + virDomainHostdevSubsysMediatedDevPtr src =3D &hostdev->source.subs= ys.u.mdev; + virMediatedDevicePtr mdev; + + if (hostdev->mode !=3D VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) + continue; + if (hostdev->source.subsys.type !=3D VIR_DOMAIN_HOSTDEV_SUBSYS_TYP= E_MDEV) + continue; + + if (!(mdev =3D virMediatedDeviceNew(src->uuidstr))) + goto cleanup; + + if (virHostdevMediatedDeviceIsUsed(mdev, mgr->activeMediatedHostde= vs)) + goto cleanup; + + /* Check whether the user-provided model corresponds with the actu= ally + * supported mediated device's API. + */ + if (virHostdevMediatedDeviceCheckModel(mdev, src->model) < 0) + 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 cop= y the + * references to the driver list + */ + if (virHostdevMarkMediatedDevices(mgr, drv_name, dom_name, list) < 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 =3D virMediatedDeviceListGet(list, 0); + virMediatedDeviceListSteal(list, tmp); + } + + ret =3D 0; + cleanup: + virObjectUnref(list); + return ret; +} + void virHostdevReAttachUSBDevices(virHostdevManagerPtr mgr, const char *drv_name, diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h index 4c1fea3..b077089 100644 --- a/src/util/virhostdev.h +++ b/src/util/virhostdev.h @@ -31,6 +31,7 @@ # include "virusb.h" # include "virscsi.h" # include "virscsivhost.h" +# include "virmdev.h" # include "domain_conf.h" =20 typedef enum { @@ -55,6 +56,7 @@ struct _virHostdevManager { virUSBDeviceListPtr activeUSBHostdevs; virSCSIDeviceListPtr activeSCSIHostdevs; virSCSIVHostDeviceListPtr activeSCSIVHostHostdevs; + virMediatedDeviceListPtr activeMediatedHostdevs; }; =20 virHostdevManagerPtr virHostdevManagerGetDefault(void); @@ -96,6 +98,13 @@ virHostdevPrepareSCSIVHostDevices(virHostdevManagerPtr h= ostdev_mgr, 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, --=20 2.10.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list