Check for active PCI devices when doing nodedevice operations.

In the current libvirt PCI code, there is no checking whether
a PCI device is in use by a guest when doing node device
detach or reattach.  This causes problems when a device is
assigned to a guest, and the administrator starts issuing
nodedevice commands.  Make it so that we check the list
of active devices when trying to detach/reattach, and only
allow the operation if the device is not assigned to a guest.

Signed-off-by: Chris Lalancette <clalance@redhat.com>
This commit is contained in:
Chris Lalancette 2010-06-14 17:12:35 -04:00
parent 415b14903e
commit 53a1db4dfc
4 changed files with 33 additions and 15 deletions

View File

@ -2865,7 +2865,7 @@ qemuPrepareHostPCIDevices(struct qemud_driver *driver,
goto cleanup; goto cleanup;
if (pciDeviceGetManaged(dev) && if (pciDeviceGetManaged(dev) &&
pciDettachDevice(dev) < 0) pciDettachDevice(dev, driver->activePciHostdevs) < 0)
goto cleanup; goto cleanup;
} }
@ -2967,7 +2967,7 @@ qemuPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
static void static void
qemudReattachManagedDevice(pciDevice *dev) qemudReattachManagedDevice(pciDevice *dev, struct qemud_driver *driver)
{ {
int retries = 100; int retries = 100;
@ -2977,7 +2977,7 @@ qemudReattachManagedDevice(pciDevice *dev)
usleep(100*1000); usleep(100*1000);
retries--; retries--;
} }
if (pciReAttachDevice(dev) < 0) { if (pciReAttachDevice(dev, driver->activePciHostdevs) < 0) {
virErrorPtr err = virGetLastError(); virErrorPtr err = virGetLastError();
VIR_ERROR(_("Failed to re-attach PCI device: %s"), VIR_ERROR(_("Failed to re-attach PCI device: %s"),
err ? err->message : _("unknown error")); err ? err->message : _("unknown error"));
@ -3024,7 +3024,7 @@ qemuDomainReAttachHostDevices(struct qemud_driver *driver,
for (i = 0; i < pciDeviceListCount(pcidevs); i++) { for (i = 0; i < pciDeviceListCount(pcidevs); i++) {
pciDevice *dev = pciDeviceListGet(pcidevs, i); pciDevice *dev = pciDeviceListGet(pcidevs, i);
qemudReattachManagedDevice(dev); qemudReattachManagedDevice(dev, driver);
} }
pciDeviceListFree(pcidevs); pciDeviceListFree(pcidevs);
@ -7772,7 +7772,7 @@ static int qemudDomainAttachHostPciDevice(struct qemud_driver *driver,
return -1; return -1;
if (!pciDeviceIsAssignable(pci, !driver->relaxedACS) || if (!pciDeviceIsAssignable(pci, !driver->relaxedACS) ||
(hostdev->managed && pciDettachDevice(pci) < 0) || (hostdev->managed && pciDettachDevice(pci, driver->activePciHostdevs) < 0) ||
pciResetDevice(pci, driver->activePciHostdevs) < 0) { pciResetDevice(pci, driver->activePciHostdevs) < 0) {
pciFreeDevice(pci); pciFreeDevice(pci);
return -1; return -1;
@ -7860,7 +7860,7 @@ error:
if (pciResetDevice(pci, driver->activePciHostdevs) < 0) if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
VIR_WARN0("Unable to reset PCI device after assign failure"); VIR_WARN0("Unable to reset PCI device after assign failure");
else if (hostdev->managed && else if (hostdev->managed &&
pciReAttachDevice(pci) < 0) pciReAttachDevice(pci, driver->activePciHostdevs) < 0)
VIR_WARN0("Unable to re-attach PCI device after assign failure"); VIR_WARN0("Unable to re-attach PCI device after assign failure");
pciFreeDevice(pci); pciFreeDevice(pci);
@ -8771,7 +8771,7 @@ static int qemudDomainDetachHostPciDevice(struct qemud_driver *driver,
pciDeviceListDel(driver->activePciHostdevs, pci); pciDeviceListDel(driver->activePciHostdevs, pci);
if (pciResetDevice(pci, driver->activePciHostdevs) < 0) if (pciResetDevice(pci, driver->activePciHostdevs) < 0)
ret = -1; ret = -1;
qemudReattachManagedDevice(pci); qemudReattachManagedDevice(pci, driver);
pciFreeDevice(pci); pciFreeDevice(pci);
} }
@ -11277,6 +11277,7 @@ out:
static int static int
qemudNodeDeviceDettach (virNodeDevicePtr dev) qemudNodeDeviceDettach (virNodeDevicePtr dev)
{ {
struct qemud_driver *driver = dev->conn->privateData;
pciDevice *pci; pciDevice *pci;
unsigned domain, bus, slot, function; unsigned domain, bus, slot, function;
int ret = -1; int ret = -1;
@ -11288,11 +11289,13 @@ qemudNodeDeviceDettach (virNodeDevicePtr dev)
if (!pci) if (!pci)
return -1; return -1;
if (pciDettachDevice(pci) < 0) qemuDriverLock(driver);
if (pciDettachDevice(pci, driver->activePciHostdevs) < 0)
goto out; goto out;
ret = 0; ret = 0;
out: out:
qemuDriverUnlock(driver);
pciFreeDevice(pci); pciFreeDevice(pci);
return ret; return ret;
} }
@ -11300,6 +11303,7 @@ out:
static int static int
qemudNodeDeviceReAttach (virNodeDevicePtr dev) qemudNodeDeviceReAttach (virNodeDevicePtr dev)
{ {
struct qemud_driver *driver = dev->conn->privateData;
pciDevice *pci; pciDevice *pci;
unsigned domain, bus, slot, function; unsigned domain, bus, slot, function;
int ret = -1; int ret = -1;
@ -11311,11 +11315,13 @@ qemudNodeDeviceReAttach (virNodeDevicePtr dev)
if (!pci) if (!pci)
return -1; return -1;
if (pciReAttachDevice(pci) < 0) qemuDriverLock(driver);
if (pciReAttachDevice(pci, driver->activePciHostdevs) < 0)
goto out; goto out;
ret = 0; ret = 0;
out: out:
qemuDriverUnlock(driver);
pciFreeDevice(pci); pciFreeDevice(pci);
return ret; return ret;
} }

View File

@ -814,7 +814,7 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver)
} }
int int
pciDettachDevice(pciDevice *dev) pciDettachDevice(pciDevice *dev, pciDeviceList *activeDevs)
{ {
const char *driver = pciFindStubDriver(); const char *driver = pciFindStubDriver();
if (!driver) { if (!driver) {
@ -823,6 +823,12 @@ pciDettachDevice(pciDevice *dev)
return -1; return -1;
} }
if (activeDevs && pciDeviceListFind(activeDevs, dev)) {
pciReportError(VIR_ERR_INTERNAL_ERROR,
_("Not detaching active device %s"), dev->name);
return -1;
}
return pciBindDeviceToStub(dev, driver); return pciBindDeviceToStub(dev, driver);
} }
@ -875,7 +881,7 @@ pciUnBindDeviceFromStub(pciDevice *dev, const char *driver)
} }
int int
pciReAttachDevice(pciDevice *dev) pciReAttachDevice(pciDevice *dev, pciDeviceList *activeDevs)
{ {
const char *driver = pciFindStubDriver(); const char *driver = pciFindStubDriver();
if (!driver) { if (!driver) {
@ -884,6 +890,12 @@ pciReAttachDevice(pciDevice *dev)
return -1; return -1;
} }
if (activeDevs && pciDeviceListFind(activeDevs, dev)) {
pciReportError(VIR_ERR_INTERNAL_ERROR,
_("Not reattaching active device %s"), dev->name);
return -1;
}
return pciUnBindDeviceFromStub(dev, driver); return pciUnBindDeviceFromStub(dev, driver);
} }

View File

@ -32,8 +32,8 @@ pciDevice *pciGetDevice (unsigned domain,
unsigned slot, unsigned slot,
unsigned function); unsigned function);
void pciFreeDevice (pciDevice *dev); void pciFreeDevice (pciDevice *dev);
int pciDettachDevice (pciDevice *dev); int pciDettachDevice (pciDevice *dev, pciDeviceList *activeDevs);
int pciReAttachDevice (pciDevice *dev); int pciReAttachDevice (pciDevice *dev, pciDeviceList *activeDevs);
int pciResetDevice (pciDevice *dev, int pciResetDevice (pciDevice *dev,
pciDeviceList *activeDevs); pciDeviceList *activeDevs);
void pciDeviceSetManaged(pciDevice *dev, void pciDeviceSetManaged(pciDevice *dev,

View File

@ -1846,7 +1846,7 @@ xenUnifiedNodeDeviceDettach (virNodeDevicePtr dev)
if (!pci) if (!pci)
return -1; return -1;
if (pciDettachDevice(pci) < 0) if (pciDettachDevice(pci, NULL) < 0)
goto out; goto out;
ret = 0; ret = 0;
@ -1869,7 +1869,7 @@ xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev)
if (!pci) if (!pci)
return -1; return -1;
if (pciReAttachDevice(pci) < 0) if (pciReAttachDevice(pci, NULL) < 0)
goto out; goto out;
ret = 0; ret = 0;