From nobody Wed Feb 11 04:39:48 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1498230354434722.2840708298595; Fri, 23 Jun 2017 08:05:54 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 43144BC6BC; Fri, 23 Jun 2017 15:05:48 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id EF2786129E; Fri, 23 Jun 2017 15:05:47 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id A6AA426A; Fri, 23 Jun 2017 15:05:47 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v5NF5j9N004561 for ; Fri, 23 Jun 2017 11:05:45 -0400 Received: by smtp.corp.redhat.com (Postfix) id 40F266F9C5; Fri, 23 Jun 2017 15:05:45 +0000 (UTC) Received: from inaba.usersys.redhat.com (ovpn-12-57.pek2.redhat.com [10.72.12.57]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 63BF16F9CD for ; Fri, 23 Jun 2017 15:05:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 43144BC6BC Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 43144BC6BC From: Andrea Bolognani To: libvir-list@redhat.com Date: Fri, 23 Jun 2017 23:03:26 +0800 Message-Id: <1498230208-14144-25-git-send-email-abologna@redhat.com> In-Reply-To: <1498230208-14144-1-git-send-email-abologna@redhat.com> References: <1498230208-14144-1-git-send-email-abologna@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v3 24/26] conf: Implement isolation rules 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-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 23 Jun 2017 15:05:49 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" These rules will make it possible for libvirt to automatically assign PCI addresses in a way that respects any isolation constraints devices might have. Signed-off-by: Andrea Bolognani Reviewed-by: Laine Stump --- src/conf/domain_addr.c | 104 +++++++++++++++++++++++++++++++++++++++++++++= +--- 1 file changed, 99 insertions(+), 5 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 48af1f5..22ff014 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -534,7 +534,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressReserveAddrInternal(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr, virDomainPCIConnectFlags flags, - int isolationGroup ATTRIBUTE_UNUSED, + int isolationGroup, bool fromConfig) { int ret =3D -1; @@ -542,6 +542,8 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAddr= essSetPtr addrs, virDomainPCIAddressBusPtr bus; virErrorNumber errType =3D (fromConfig ? VIR_ERR_XML_ERROR : VIR_ERR_INTERNAL_ERROR= ); + bool firstDevice; + size_t slot; =20 if (!(addrStr =3D virDomainPCIAddressAsString(addr))) goto cleanup; @@ -572,6 +574,36 @@ virDomainPCIAddressReserveAddrInternal(virDomainPCIAdd= ressSetPtr addrs, bus->slot[addr->slot].aggregate =3D true; } =20 + /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + firstDevice =3D true; + for (slot =3D bus->minSlot; slot <=3D bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice =3D false; + break; + } + } + + if (firstDevice && !bus->isolationGroupLocked) { + /* The first device decides the isolation group for the + * entire bus */ + bus->isolationGroup =3D isolationGroup; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because o= f " + "first device %s", + addr->domain, addr->bus, isolationGroup, addrStr); + } else if (bus->isolationGroup !=3D isolationGroup && fromConfig) { + /* If this is not the first function and its isolation group + * doesn't match the bus', then it should not be using this + * address. However, if the address comes from the user then + * we comply with the request and change the isolation group + * back to the default (because at that point isolation can't + * be guaranteed anymore) */ + bus->isolationGroup =3D 0; + VIR_DEBUG("PCI bus %.4x:%.2x assigned isolation group %d because o= f " + "user assigned address %s", + addr->domain, addr->bus, isolationGroup, addrStr); + } + /* mark the requested function as reserved */ bus->slot[addr->slot].functions |=3D (1 << addr->function); VIR_DEBUG("Reserving PCI address %s (aggregate=3D'%s')", addrStr, @@ -643,7 +675,28 @@ int virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr addr) { - addrs->buses[addr->bus].slot[addr->slot].functions &=3D ~(1 << addr->f= unction); + virDomainPCIAddressBusPtr bus =3D &addrs->buses[addr->bus]; + bool lastDevice; + size_t slot; + + bus->slot[addr->slot].functions &=3D ~(1 << addr->function); + + /* Figure out whether this is the first device we're plugging + * into the bus by looking at all the slots */ + lastDevice =3D true; + for (slot =3D bus->minSlot; slot <=3D bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + lastDevice =3D false; + break; + } + } + + /* If the one we just unplugged was the last device on the bus, + * we can reset the isolation group for the bus so that any + * device we'll try to plug in from now on will be accepted */ + if (lastDevice && !bus->isolationGroupLocked) + bus->isolationGroup =3D 0; + return 0; } =20 @@ -749,7 +802,7 @@ static int ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPtr addrs, virPCIDeviceAddressPtr next_addr, virDomainPCIConnectFlags flags, - int isolationGroup ATTRIBUTE_UNUSED, + int isolationGroup, int function) { virPCIDeviceAddress a =3D { 0 }; @@ -765,11 +818,50 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSet= Ptr addrs, else a.function =3D function; =20 - /* "Begin at the beginning," the King said, very gravely, "and go on - * till you come to the end: then stop." */ + /* When looking for a suitable bus for the device, start by being + * very strict and ignoring all those where the isolation groups + * don't match. This ensures all devices sharing the same isolation + * group will end up on the same group */ + for (a.bus =3D 0; a.bus < addrs->nbuses; a.bus++) { + virDomainPCIAddressBusPtr bus =3D &addrs->buses[a.bus]; + bool found =3D false; + + if (bus->isolationGroup !=3D isolationGroup) + continue; + + a.slot =3D bus->minSlot; + + if (virDomainPCIAddressFindUnusedFunctionOnBus(bus, &a, function, + flags, &found) < 0)= { + goto error; + } + + if (found) + goto success; + } + + /* We haven't been able to find a perfectly matching bus, but we + * might still be able to make this work by altering the isolation + * group for a bus that's currently empty. So let's try that */ for (a.bus =3D 0; a.bus < addrs->nbuses; a.bus++) { virDomainPCIAddressBusPtr bus =3D &addrs->buses[a.bus]; bool found =3D false; + bool firstDevice =3D true; + size_t slot; + + /* Go through all the slots and see whether they are empty */ + for (slot =3D bus->minSlot; slot <=3D bus->maxSlot; slot++) { + if (bus->slot[slot].functions) { + firstDevice =3D false; + break; + } + } + + /* We can only change the isolation group for a bus when + * plugging in the first device; moreover, some buses are + * prevented from ever changing it */ + if (!firstDevice || bus->isolationGroupLocked) + continue; =20 a.slot =3D bus->minSlot; =20 @@ -778,6 +870,8 @@ virDomainPCIAddressGetNextAddr(virDomainPCIAddressSetPt= r addrs, goto error; } =20 + /* The isolation group for the bus will actually be changed + * later, in virDomainPCIAddressReserveAddrInternal() */ if (found) goto success; } --=20 2.7.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list