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 <yuzhang@redhat.com>
This commit is contained in:
Yufang Zhang 2011-04-27 20:09:12 +08:00 committed by Eric Blake
parent f7bd72fa26
commit a88916665d
2 changed files with 68 additions and 0 deletions

View File

@ -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....]

View 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;