On 01/17/2012 01:02 PM, Osier Yang wrote:
> pciTrySecondaryBusReset checks if there is active device on the
> same bus, however, qemu driver doesn't maintain an effective
> list for the inactive devices, and it passes meaningless argment
s/argment/argument/
> for parameter "inactiveDevs". e.g. (qemuPrepareHostdevPCIDevices)
>
> if (!(pcidevs = qemuGetPciHostDeviceList(hostdevs, nhostdevs)))
> return -1;
>
> ...skipped...
>
> if (pciResetDevice(dev, driver->activePciHostdevs, pcidevs)< 0)
> goto reattachdevs;
>
> NB, the "pcidevs" used above are extracted from domain def, and
> thus one won't be able to attach a device of which bus has other
> device even detached from host (nodedev-detach). To see more
> details of the problem:
>
> RHBZ:
https://bugzilla.redhat.com/show_bug.cgi?id=773667
>
> This patch is to resolve the problem by introduce an inactive
s/introduce/introducing/
> PCI device list (just like qemu_driver->activePciHostdevs), and
> the whole logic is:
>
> * Add the device to inactive list when do nodedev-dettach
s/when do/during/
> * Remove the device from inactive list when do nodedev-reattach
> * Remove the device from inactive list when do attach-device
> (for not managed device)
> * Add the device to inactive list after detach-device, only
> if the device is not managed
>
> With above, we have sufficient inactive PCI device list, and thus
> we can use it for pciResetDevice. e.g.(qemuPrepareHostdevPCIDevices)
>
> if (pciResetDevice(dev, driver->activePciHostdevs,
> driver->inactivePciHostdevs)< 0)
> goto reattachdevs;
>
> v1 ~ v2
>
> Fixed a potential crash.
> ---
> Got a testing box from Miroslav and tested the patch, it works well.
I'm glad you were able to test it; I tried to reproduce things locally,
but didn't quite have the right hardware, so I'm reviewing this on
inspection alone. But it is a serious enough issue that I'm okay
pushing once the nits are fixed.
> ---
> src/qemu/qemu_conf.h | 5 +++++
> src/qemu/qemu_driver.c | 19 +++++++++++++++----
> src/qemu/qemu_hostdev.c | 32 +++++++++++++++++++++++---------
> src/util/pci.c | 28 ++++++++++++++++++++++++----
> src/util/pci.h | 8 ++++++--
> src/xen/xen_driver.c | 4 ++--
> 7 files changed, 77 insertions(+), 22 deletions(-)
>
> diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
> index d8d7915..3f1b668 100644
> --- a/src/qemu/qemu_conf.h
> +++ b/src/qemu/qemu_conf.h
> @@ -128,6 +128,11 @@ struct qemud_driver {
> pciDeviceList *activePciHostdevs;
> usbDeviceList *activeUsbHostdevs;
>
> + /* The device which is not used by both host
> + * and any guest.
The devices which are not in use by the host or any guest.
> @@ -778,6 +781,7 @@ qemudShutdown(void) {
>
> qemuDriverLock(qemu_driver);
> pciDeviceListFree(qemu_driver->activePciHostdevs);
> + pciDeviceListFree(qemu_driver->inactivePciHostdevs);
> usbDeviceListFree(qemu_driver->activeUsbHostdevs);
We'll probably have to repeat this exercise for USB passthrough devices,
but that can be a separate patch.
> @@ -445,8 +452,13 @@ void qemuReattachPciDevice(pciDevice *dev, struct qemud_driver
*driver)
> {
> int retries = 100;
>
> - if (!pciDeviceGetManaged(dev))
> + /* If the device is not managed and was attached to guest
> + * successfully, it must had be inactive.
s/had be/have been/
Overall, the design looks sound. I squashed in your followup, plus
this, then pushed: