]> xenbits.xensource.com Git - libvirt.git/commitdiff
xen: check if device is assigned to guest before reattaching
authorYufang Zhang <yuzhang@redhat.com>
Wed, 27 Apr 2011 12:09:12 +0000 (20:09 +0800)
committerEric Blake <eblake@redhat.com>
Thu, 28 Apr 2011 20:45:31 +0000 (14:45 -0600)
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 <yuzhang@redhat.com>
AUTHORS
src/xen/xen_driver.c

diff --git a/AUTHORS b/AUTHORS
index 10124ee5cf8dc550957d939b12101ccb6f5ee637..877fb03ac716dbd0595aadf6a3750ac1dd036f51 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -168,6 +168,7 @@ Patches have also been contributed by:
   Alexander Todorov    <atodorov@otb.bg>
   Richard Laager       <rlaager@wiktel.com>
   Mark Wu              <dwu@redhat.com>
+  Yufang Zhang         <yuzhang@redhat.com>
 
   [....send patches to get your name here....]
 
index 2a07b7bd049f9bfcd5bd53ef9cf96d1e05bc2cc2..dd94fbc12cd6769b021fe6124465bed372b91dc3 100644 (file)
@@ -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;