ia64/linux-2.6.18-xen.hg

view drivers/pci/bus.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 f7a2c0985f99
children
line source
1 /*
2 * drivers/pci/bus.c
3 *
4 * From setup-res.c, by:
5 * Dave Rusling (david.rusling@reo.mts.dec.com)
6 * David Mosberger (davidm@cs.arizona.edu)
7 * David Miller (davem@redhat.com)
8 * Ivan Kokshaysky (ink@jurassic.park.msu.ru)
9 */
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/pci.h>
13 #include <linux/errno.h>
14 #include <linux/ioport.h>
15 #include <linux/proc_fs.h>
16 #include <linux/init.h>
18 #include "pci.h"
20 /**
21 * pci_bus_alloc_resource - allocate a resource from a parent bus
22 * @bus: PCI bus
23 * @res: resource to allocate
24 * @size: size of resource to allocate
25 * @align: alignment of resource to allocate
26 * @min: minimum /proc/iomem address to allocate
27 * @type_mask: IORESOURCE_* type flags
28 * @alignf: resource alignment function
29 * @alignf_data: data argument for resource alignment function
30 *
31 * Given the PCI bus a device resides on, the size, minimum address,
32 * alignment and type, try to find an acceptable resource allocation
33 * for a specific device resource.
34 */
35 int
36 pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
37 resource_size_t size, resource_size_t align,
38 resource_size_t min, unsigned int type_mask,
39 void (*alignf)(void *, struct resource *, resource_size_t,
40 resource_size_t),
41 void *alignf_data)
42 {
43 int i, ret = -ENOMEM;
45 type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
47 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
48 struct resource *r = bus->resource[i];
49 if (!r)
50 continue;
52 /* type_mask must match */
53 if ((res->flags ^ r->flags) & type_mask)
54 continue;
56 /* We cannot allocate a non-prefetching resource
57 from a pre-fetching area */
58 if ((r->flags & IORESOURCE_PREFETCH) &&
59 !(res->flags & IORESOURCE_PREFETCH))
60 continue;
62 /* Ok, try it out.. */
63 ret = allocate_resource(r, res, size,
64 r->start ? : min,
65 -1, align,
66 alignf, alignf_data);
67 if (ret == 0)
68 break;
69 }
70 return ret;
71 }
73 /**
74 * add a single device
75 * @dev: device to add
76 *
77 * This adds a single pci device to the global
78 * device list and adds sysfs and procfs entries
79 */
80 void __devinit pci_bus_add_device(struct pci_dev *dev)
81 {
82 device_add(&dev->dev);
84 down_write(&pci_bus_sem);
85 list_add_tail(&dev->global_list, &pci_devices);
86 up_write(&pci_bus_sem);
88 pci_proc_attach_device(dev);
89 pci_create_sysfs_dev_files(dev);
90 }
92 /**
93 * pci_bus_add_devices - insert newly discovered PCI devices
94 * @bus: bus to check for new devices
95 *
96 * Add newly discovered PCI devices (which are on the bus->devices
97 * list) to the global PCI device list, add the sysfs and procfs
98 * entries. Where a bridge is found, add the discovered bus to
99 * the parents list of child buses, and recurse (breadth-first
100 * to be compatible with 2.4)
101 *
102 * Call hotplug for each new devices.
103 */
104 void __devinit pci_bus_add_devices(struct pci_bus *bus)
105 {
106 struct pci_dev *dev;
108 list_for_each_entry(dev, &bus->devices, bus_list) {
109 /*
110 * Skip already-present devices (which are on the
111 * global device list.)
112 */
113 if (!list_empty(&dev->global_list))
114 continue;
115 pci_bus_add_device(dev);
116 }
118 list_for_each_entry(dev, &bus->devices, bus_list) {
120 BUG_ON(list_empty(&dev->global_list));
122 /*
123 * If there is an unattached subordinate bus, attach
124 * it and then scan for unattached PCI devices.
125 */
126 if (dev->subordinate) {
127 if (list_empty(&dev->subordinate->node)) {
128 down_write(&pci_bus_sem);
129 list_add_tail(&dev->subordinate->node,
130 &dev->bus->children);
131 up_write(&pci_bus_sem);
132 }
133 pci_bus_add_devices(dev->subordinate);
135 sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
136 }
137 }
138 }
140 void pci_enable_bridges(struct pci_bus *bus)
141 {
142 struct pci_dev *dev;
143 int retval;
145 list_for_each_entry(dev, &bus->devices, bus_list) {
146 if (dev->subordinate) {
147 retval = pci_enable_device(dev);
148 pci_set_master(dev);
149 pci_enable_bridges(dev->subordinate);
150 }
151 }
152 }
154 /** pci_walk_bus - walk devices on/under bus, calling callback.
155 * @top bus whose devices should be walked
156 * @cb callback to be called for each device found
157 * @userdata arbitrary pointer to be passed to callback.
158 *
159 * Walk the given bus, including any bridged devices
160 * on buses under this bus. Call the provided callback
161 * on each device found.
162 */
163 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
164 void *userdata)
165 {
166 struct pci_dev *dev;
167 struct pci_bus *bus;
168 struct list_head *next;
170 bus = top;
171 down_read(&pci_bus_sem);
172 next = top->devices.next;
173 for (;;) {
174 if (next == &bus->devices) {
175 /* end of this bus, go up or finish */
176 if (bus == top)
177 break;
178 next = bus->self->bus_list.next;
179 bus = bus->self->bus;
180 continue;
181 }
182 dev = list_entry(next, struct pci_dev, bus_list);
183 if (dev->subordinate) {
184 /* this is a pci-pci bridge, do its devices next */
185 next = dev->subordinate->devices.next;
186 bus = dev->subordinate;
187 } else
188 next = dev->bus_list.next;
190 /* Run device routines with the device locked */
191 down(&dev->dev.sem);
192 cb(dev, userdata);
193 up(&dev->dev.sem);
194 }
195 up_read(&pci_bus_sem);
196 }
197 EXPORT_SYMBOL_GPL(pci_walk_bus);
199 EXPORT_SYMBOL(pci_bus_alloc_resource);
200 EXPORT_SYMBOL_GPL(pci_bus_add_device);
201 EXPORT_SYMBOL(pci_bus_add_devices);
202 EXPORT_SYMBOL(pci_enable_bridges);