From a88916665df614238b8e56806bb27caaf4cc7725 Mon Sep 17 00:00:00 2001 From: Yufang Zhang Date: Wed, 27 Apr 2011 20:09:12 +0800 Subject: [PATCH] xen: check if device is assigned to guest before reattaching Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=664059 Reattaching pci device back to host without destroying guest or detaching device from guest would cause host to crash. This patch adds a check before doing device reattach. If the device is being assigned to guest, libvirt refuses to reattach device to host. The patch only works for Xen, for it just checks xenstore to get pci device information. Signed-off-by: Yufang Zhang --- AUTHORS | 1 + src/xen/xen_driver.c | 67 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/AUTHORS b/AUTHORS index 10124ee5cf..877fb03ac7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -168,6 +168,7 @@ Patches have also been contributed by: Alexander Todorov Richard Laager Mark Wu + Yufang Zhang [....send patches to get your name here....] diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index 2a07b7bd04..dd94fbc12c 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -1926,12 +1926,71 @@ out: return ret; } +static int +xenUnifiedNodeDeviceAssignedDomainId (virNodeDevicePtr dev) +{ + int numdomains; + int ret = -1, i; + int *ids = NULL; + char *bdf = NULL; + char *xref = NULL; + unsigned int domain, bus, slot, function; + virConnectPtr conn = dev->conn; + xenUnifiedPrivatePtr priv = conn->privateData; + + /* Get active domains */ + numdomains = xenUnifiedNumOfDomains(conn); + if (numdomains < 0) { + return ret; + } + if (numdomains > 0){ + if (VIR_ALLOC_N(ids, numdomains) < 0) { + virReportOOMError(); + goto out; + } + if ((numdomains = xenUnifiedListDomains(conn, &ids[0], numdomains)) < 0) { + goto out; + } + } + + /* Get pci bdf */ + if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) + goto out; + + if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x", + domain, bus, slot, function) < 0) { + virReportOOMError(); + goto out; + } + + xenUnifiedLock(priv); + /* Check if bdf is assigned to one of active domains */ + for (i = 0; i < numdomains; i++ ) { + xref = xenStoreDomainGetPCIID(conn, ids[i], bdf); + if (xref == NULL) { + continue; + } else { + ret = ids[i]; + break; + } + } + xenUnifiedUnlock(priv); + + VIR_FREE(xref); + VIR_FREE(bdf); +out: + VIR_FREE(ids); + + return ret; +} + static int xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) { pciDevice *pci; unsigned domain, bus, slot, function; int ret = -1; + int domid; if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) return -1; @@ -1940,6 +1999,14 @@ xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev) if (!pci) return -1; + /* Check if device is assigned to an active guest */ + if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) { + xenUnifiedError(VIR_ERR_INTERNAL_ERROR, + _("Device %s has been assigned to guest %d"), + dev->name, domid); + goto out; + } + if (pciReAttachDevice(pci, NULL) < 0) goto out; -- GitLab