ia64/linux-2.6.18-xen.hg

annotate drivers/pci/remove.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
rev   line source
ian@0 1 #include <linux/pci.h>
ian@0 2 #include <linux/module.h>
ian@0 3 #include "pci.h"
ian@0 4
ian@0 5 static void pci_free_resources(struct pci_dev *dev)
ian@0 6 {
ian@0 7 int i;
ian@0 8
ian@0 9 msi_remove_pci_irq_vectors(dev);
ian@0 10
ian@0 11 pci_cleanup_rom(dev);
ian@0 12 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
ian@0 13 struct resource *res = dev->resource + i;
ian@0 14 if (res->parent)
ian@0 15 release_resource(res);
ian@0 16 }
ian@0 17 }
ian@0 18
ian@0 19 static void pci_destroy_dev(struct pci_dev *dev)
ian@0 20 {
ian@0 21 if (!list_empty(&dev->global_list)) {
ian@0 22 pci_proc_detach_device(dev);
ian@0 23 pci_remove_sysfs_dev_files(dev);
ian@0 24 device_unregister(&dev->dev);
ian@0 25 down_write(&pci_bus_sem);
ian@0 26 list_del(&dev->global_list);
ian@0 27 dev->global_list.next = dev->global_list.prev = NULL;
ian@0 28 up_write(&pci_bus_sem);
ian@0 29 }
ian@0 30
ian@0 31 /* Remove the device from the device lists, and prevent any further
ian@0 32 * list accesses from this device */
ian@0 33 down_write(&pci_bus_sem);
ian@0 34 list_del(&dev->bus_list);
ian@0 35 dev->bus_list.next = dev->bus_list.prev = NULL;
ian@0 36 up_write(&pci_bus_sem);
ian@0 37
ian@0 38 pci_free_resources(dev);
ian@0 39 pci_dev_put(dev);
ian@0 40 }
ian@0 41
ian@0 42 /**
ian@0 43 * pci_remove_device_safe - remove an unused hotplug device
ian@0 44 * @dev: the device to remove
ian@0 45 *
ian@0 46 * Delete the device structure from the device lists and
ian@0 47 * notify userspace (/sbin/hotplug), but only if the device
ian@0 48 * in question is not being used by a driver.
ian@0 49 * Returns 0 on success.
ian@0 50 */
ian@0 51 #if 0
ian@0 52 int pci_remove_device_safe(struct pci_dev *dev)
ian@0 53 {
ian@0 54 if (pci_dev_driver(dev))
ian@0 55 return -EBUSY;
ian@0 56 pci_destroy_dev(dev);
ian@0 57 return 0;
ian@0 58 }
ian@0 59 #endif /* 0 */
ian@0 60
ian@0 61 void pci_remove_bus(struct pci_bus *pci_bus)
ian@0 62 {
ian@0 63 pci_proc_detach_bus(pci_bus);
ian@0 64
ian@0 65 down_write(&pci_bus_sem);
ian@0 66 list_del(&pci_bus->node);
ian@0 67 up_write(&pci_bus_sem);
ian@0 68 pci_remove_legacy_files(pci_bus);
ian@0 69 class_device_remove_file(&pci_bus->class_dev,
ian@0 70 &class_device_attr_cpuaffinity);
ian@0 71 sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
ian@0 72 class_device_unregister(&pci_bus->class_dev);
ian@0 73 }
ian@0 74 EXPORT_SYMBOL(pci_remove_bus);
ian@0 75
ian@0 76 /**
ian@0 77 * pci_remove_bus_device - remove a PCI device and any children
ian@0 78 * @dev: the device to remove
ian@0 79 *
ian@0 80 * Remove a PCI device from the device lists, informing the drivers
ian@0 81 * that the device has been removed. We also remove any subordinate
ian@0 82 * buses and children in a depth-first manner.
ian@0 83 *
ian@0 84 * For each device we remove, delete the device structure from the
ian@0 85 * device lists, remove the /proc entry, and notify userspace
ian@0 86 * (/sbin/hotplug).
ian@0 87 */
ian@0 88 void pci_remove_bus_device(struct pci_dev *dev)
ian@0 89 {
ian@0 90 if (dev->subordinate) {
ian@0 91 struct pci_bus *b = dev->subordinate;
ian@0 92
ian@0 93 pci_remove_behind_bridge(dev);
ian@0 94 pci_remove_bus(b);
ian@0 95 dev->subordinate = NULL;
ian@0 96 }
ian@0 97
ian@0 98 pci_destroy_dev(dev);
ian@0 99 }
ian@0 100
ian@0 101 /**
ian@0 102 * pci_remove_behind_bridge - remove all devices behind a PCI bridge
ian@0 103 * @dev: PCI bridge device
ian@0 104 *
ian@0 105 * Remove all devices on the bus, except for the parent bridge.
ian@0 106 * This also removes any child buses, and any devices they may
ian@0 107 * contain in a depth-first manner.
ian@0 108 */
ian@0 109 void pci_remove_behind_bridge(struct pci_dev *dev)
ian@0 110 {
ian@0 111 struct list_head *l, *n;
ian@0 112
ian@0 113 if (dev->subordinate) {
ian@0 114 list_for_each_safe(l, n, &dev->subordinate->devices) {
ian@0 115 struct pci_dev *dev = pci_dev_b(l);
ian@0 116
ian@0 117 pci_remove_bus_device(dev);
ian@0 118 }
ian@0 119 }
ian@0 120 }
ian@0 121
ian@0 122 EXPORT_SYMBOL(pci_remove_bus_device);
ian@0 123 EXPORT_SYMBOL(pci_remove_behind_bridge);