
At 2011-7-1 18:24, Guannan Ren write:
the "virsh nodedev-reattch" command could return successfully, but the pci device is still bound to pci-stub driver. The reason is noddev-reattach trys to use the variables set by nodedev-dettach commands. Becuase these variables is not persistent, this is not we expected. the patch try to fix it.
I do not agree with this patch. You should read this mail: https://www.redhat.com/archives/libvir-list/2011-April/msg00315.html This patch will cause regression about hotpluging host pci device. I think the problem is that: the init value of these variables is wrong. We can fix this bug by modifing pciGetDevice() or its caller.
--- src/util/pci.c | 74 +++++++++++++++++++------------------------------------ 1 files changed, 26 insertions(+), 48 deletions(-)
diff --git a/src/util/pci.c b/src/util/pci.c index 46a3a83..d345c3e 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -67,9 +67,6 @@ struct _pciDevice { unsigned managed : 1;
/* used by reattach function */ - unsigned unbind_from_stub : 1; - unsigned remove_slot : 1; - unsigned reprobe : 1; };
struct _pciDeviceList { @@ -882,14 +879,23 @@ pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) if (pciDriverDir(&drvdir, driver)< 0) goto cleanup;
- if (!dev->unbind_from_stub) - goto remove_slot; - - /* If the device is bound to stub, unbind it. - */ if (pciDeviceFile(&path, dev->name, "driver")< 0) goto cleanup;
+ /* If the device is bound to a driver instead of pci-stub, do nothing. + */ + if (virFileExists(path)&& ! virFileLinkPointsTo(path, drvdir)){ + result = 0; + goto cleanup; + } + + /* If the device is not bound to any driver, reprobe it. + */ + if (!virFileExists(path)) + goto reprobe; + + /* If the device is bound to stub, unbind it. + */ if (virFileExists(drvdir)&& virFileLinkPointsTo(path, drvdir)) { if (pciDriverFile(&path, driver, "unbind")< 0) { goto cleanup; @@ -902,11 +908,6 @@ pciUnbindDeviceFromStub(pciDevice *dev, const char *driver) goto cleanup; } } - dev->unbind_from_stub = 0; - -remove_slot: - if (!dev->remove_slot) - goto reprobe;
/* Xen's pciback.ko wants you to use remove_slot on the specific device */ if (pciDriverFile(&path, driver, "remove_slot")< 0) { @@ -919,14 +920,8 @@ remove_slot: dev->name, driver); goto cleanup; } - dev->remove_slot = 0;
reprobe: - if (!dev->reprobe) { - result = 0; - goto cleanup; - } - /* Trigger a re-probe of the device is not in the stub's dynamic * ID table. If the stub is available, but 'remove_id' isn't * available, then re-probing would just cause the device to be @@ -935,6 +930,12 @@ reprobe: if (pciDriverFile(&path, driver, "remove_id")< 0) { goto cleanup; } + + /* If the device is still in stub's dynamic ID table,remove it, + * otherwise, ignore the error. + */ + if (virFileExists(path)&& virFileWriteStr(path, dev->name, 0)< 0){ + }
if (!virFileExists(drvdir) || virFileExists(path)) { if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0)< 0) { @@ -948,11 +949,6 @@ reprobe: result = 0;
cleanup: - /* do not do it again */ - dev->unbind_from_stub = 0; - dev->remove_slot = 0; - dev->reprobe = 0; - VIR_FREE(drvdir); VIR_FREE(path);
@@ -966,7 +962,6 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) int result = -1; char *drvdir = NULL; char *path = NULL; - int reprobe = 0;
/* check whether the device is already bound to a driver */ if (pciDriverDir(&drvdir, driver)< 0 || @@ -980,7 +975,6 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) result = 0; goto cleanup; } - reprobe = 1; }
/* Add the PCI device ID to the stub's dynamic ID table; @@ -1011,8 +1005,7 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) }
if (virFileLinkPointsTo(path, drvdir)) { - dev->unbind_from_stub = 1; - dev->remove_slot = 1; + result = 0; goto remove_id; }
@@ -1022,7 +1015,7 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) * your root filesystem. */ if (pciDeviceFile(&path, dev->name, "driver/unbind")< 0) { - goto cleanup; + goto remove_id; }
if (virFileExists(path)) { @@ -1030,9 +1023,8 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) virReportSystemError(errno, _("Failed to unbind PCI device '%s'"), dev->name); - goto cleanup; + goto remove_id; } - dev->reprobe = reprobe; }
/* If the device isn't already bound to pci-stub, try binding it now. @@ -1054,7 +1046,6 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) dev->name, driver); goto remove_id; } - dev->remove_slot = 1;
if (pciDriverFile(&path, driver, "bind")< 0) { goto remove_id; @@ -1066,20 +1057,15 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) dev->name, driver); goto remove_id; } - dev->unbind_from_stub = 1; }
+ result = 0; remove_id: /* If 'remove_id' exists, remove the device id from pci-stub's dynamic * ID table so that 'drivers_probe' works below. */ if (pciDriverFile(&path, driver, "remove_id")< 0) { - /* We do not remove PCI ID from pci-stub, and we cannot reprobe it */ - if (dev->reprobe) { - VIR_WARN("Could not remove PCI ID '%s' from %s, and the device " - "cannot be probed again.", dev->id, driver); - } - dev->reprobe = 0; + result = -1; goto cleanup; }
@@ -1087,18 +1073,10 @@ remove_id: virReportSystemError(errno, _("Failed to remove PCI ID '%s' from %s"), dev->id, driver); - - /* remove PCI ID from pci-stub failed, and we cannot reprobe it */ - if (dev->reprobe) { - VIR_WARN("Failed to remove PCI ID '%s' from %s, and the device " - "cannot be probed again.", dev->id, driver); - } - dev->reprobe = 0; + result = -1; goto cleanup; }
- result = 0; - cleanup: VIR_FREE(drvdir); VIR_FREE(path);