diff --git a/src/util/pci.c b/src/util/pci.c index 8d2dbb09b7a896ebd18b3a428fc24ac22842323a..6ed96f4fd27efe5ca70f005f865f208a96ae3d37 100644 --- a/src/util/pci.c +++ b/src/util/pci.c @@ -775,38 +775,72 @@ pciResetDevice(pciDevice *dev, } -static void -pciDriverDir(char *buf, size_t buflen, const char *driver) +static int +pciDriverDir(char **buffer, const char *driver) { - snprintf(buf, buflen, PCI_SYSFS "drivers/%s", driver); + VIR_FREE(*buffer); + + if (virAsprintf(buffer, PCI_SYSFS "drivers/%s", driver) < 0) { + virReportOOMError(); + return -1; + } + + return 0; } -static void -pciDriverFile(char *buf, size_t buflen, const char *driver, const char *file) +static int +pciDriverFile(char **buffer, const char *driver, const char *file) { - snprintf(buf, buflen, PCI_SYSFS "drivers/%s/%s", driver, file); + VIR_FREE(*buffer); + + if (virAsprintf(buffer, PCI_SYSFS "drivers/%s/%s", driver, file) < 0) { + virReportOOMError(); + return -1; + } + + return 0; } -static void -pciDeviceFile(char *buf, size_t buflen, const char *device, const char *file) +static int +pciDeviceFile(char **buffer, const char *device, const char *file) { - snprintf(buf, buflen, PCI_SYSFS "devices/%s/%s", device, file); + VIR_FREE(*buffer); + + if (virAsprintf(buffer, PCI_SYSFS "devices/%s/%s", device, file) < 0) { + virReportOOMError(); + return -1; + } + + return 0; } static const char * pciFindStubDriver(void) { - char drvpath[PATH_MAX]; + char *drvpath = NULL; int probed = 0; recheck: - pciDriverDir(drvpath, sizeof(drvpath), "pci-stub"); - if (virFileExists(drvpath)) + if (pciDriverDir(&drvpath, "pci-stub") < 0) { + return NULL; + } + + if (virFileExists(drvpath)) { + VIR_FREE(drvpath); return "pci-stub"; - pciDriverDir(drvpath, sizeof(drvpath), "pciback"); - if (virFileExists(drvpath)) + } + + if (pciDriverDir(&drvpath, "pciback") < 0) { + return NULL; + } + + if (virFileExists(drvpath)) { + VIR_FREE(drvpath); return "pciback"; + } + + VIR_FREE(drvpath); if (!probed) { const char *const stubprobe[] = { MODPROBE, "pci-stub", NULL }; @@ -837,8 +871,9 @@ recheck: static int pciBindDeviceToStub(pciDevice *dev, const char *driver) { - char drvdir[PATH_MAX]; - char path[PATH_MAX]; + int result = -1; + char *drvdir = NULL; + char *path = NULL; /* Add the PCI device ID to the stub's dynamic ID table; * this is needed to allow us to bind the device to the stub. @@ -848,12 +883,15 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) * is triggered for such a device, it will also be immediately * bound by the stub. */ - pciDriverFile(path, sizeof(path), driver, "new_id"); + if (pciDriverFile(&path, driver, "new_id") < 0) { + return -1; + } + if (virFileWriteStr(path, dev->id, 0) < 0) { virReportSystemError(errno, _("Failed to add PCI device ID '%s' to %s"), dev->id, driver); - return -1; + goto cleanup; } /* If the device is already bound to a driver, unbind it. @@ -861,48 +899,69 @@ pciBindDeviceToStub(pciDevice *dev, const char *driver) * PCI device happens to be IDE controller for the disk hosting * your root filesystem. */ - pciDeviceFile(path, sizeof(path), dev->name, "driver/unbind"); + if (pciDeviceFile(&path, dev->name, "driver/unbind") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to unbind PCI device '%s'"), dev->name); - return -1; + goto cleanup; } /* If the device isn't already bound to pci-stub, try binding it now. */ - pciDriverDir(drvdir, sizeof(drvdir), driver); - pciDeviceFile(path, sizeof(path), dev->name, "driver"); + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto cleanup; + } + if (!virFileLinkPointsTo(path, drvdir)) { /* Xen's pciback.ko wants you to use new_slot first */ - pciDriverFile(path, sizeof(path), driver, "new_slot"); + if (pciDriverFile(&path, driver, "new_slot") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to add slot for PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; + } + + if (pciDriverFile(&path, driver, "bind") < 0) { + goto cleanup; } - pciDriverFile(path, sizeof(path), driver, "bind"); if (virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to bind PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; } } /* If 'remove_id' exists, remove the device id from pci-stub's dynamic * ID table so that 'drivers_probe' works below. */ - pciDriverFile(path, sizeof(path), driver, "remove_id"); + if (pciDriverFile(&path, driver, "remove_id") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->id, 0) < 0) { virReportSystemError(errno, _("Failed to remove PCI ID '%s' from %s"), dev->id, driver); - return -1; + goto cleanup; } - return 0; + result = 0; + +cleanup: + VIR_FREE(drvdir); + VIR_FREE(path); + + return result; } int @@ -927,49 +986,67 @@ pciDettachDevice(pciDevice *dev, pciDeviceList *activeDevs) static int pciUnBindDeviceFromStub(pciDevice *dev, const char *driver) { - char drvdir[PATH_MAX]; - char path[PATH_MAX]; + int result = -1; + char *drvdir = NULL; + char *path = NULL; /* If the device is bound to stub, unbind it. */ - pciDriverDir(drvdir, sizeof(drvdir), driver); - pciDeviceFile(path, sizeof(path), dev->name, "driver"); + if (pciDriverDir(&drvdir, driver) < 0 || + pciDeviceFile(&path, dev->name, "driver") < 0) { + goto cleanup; + } + if (virFileExists(drvdir) && virFileLinkPointsTo(path, drvdir)) { - pciDriverFile(path, sizeof(path), driver, "unbind"); + if (pciDriverFile(&path, driver, "unbind") < 0) { + goto cleanup; + } + if (virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to bind PCI device '%s' to %s"), dev->name, driver); - return -1; + goto cleanup; } } /* Xen's pciback.ko wants you to use remove_slot on the specific device */ - pciDriverFile(path, sizeof(path), driver, "remove_slot"); + if (pciDriverFile(&path, driver, "remove_slot") < 0) { + goto cleanup; + } + if (virFileExists(path) && virFileWriteStr(path, dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to remove slot for PCI device '%s' to %s"), dev->name, driver); - return -1; + 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 * re-bound to the stub. */ - pciDriverFile(path, sizeof(path), driver, "remove_id"); + if (pciDriverFile(&path, driver, "remove_id") < 0) { + goto cleanup; + } + if (!virFileExists(drvdir) || virFileExists(path)) { if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name, 0) < 0) { virReportSystemError(errno, _("Failed to trigger a re-probe for PCI device '%s'"), dev->name); - return -1; + goto cleanup; } } - return 0; + result = 0; + +cleanup: + VIR_FREE(drvdir); + VIR_FREE(path); + + return result; } int @@ -1103,15 +1180,20 @@ pciWaitForDeviceCleanup(pciDevice *dev, const char *matcher) static char * pciReadDeviceID(pciDevice *dev, const char *id_name) { - char path[PATH_MAX]; + char *path; char *id_str; - snprintf(path, sizeof(path), PCI_SYSFS "devices/%s/%s", - dev->name, id_name); + if (pciDeviceFile(&path, dev->name, id_name) < 0) { + return NULL; + } /* ID string is '0xNNNN\n' ... i.e. 7 bytes */ - if (virFileReadAll(path, 7, &id_str) < 0) + if (virFileReadAll(path, 7, &id_str) < 0) { + VIR_FREE(path); return NULL; + } + + VIR_FREE(path); /* Check for 0x suffix */ if (id_str[0] != '0' || id_str[1] != 'x') {