ia64/linux-2.6.18-xen.hg

view drivers/pci/reserve.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 20be7f6d414a
children
line source
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright (c) 2009 Isaku Yamahata
17 * VA Linux Systems Japan K.K.
18 *
19 */
21 #include <linux/kernel.h>
22 #include <linux/pci.h>
24 #include <asm/setup.h>
26 static char pci_reserve_param[COMMAND_LINE_SIZE];
28 /* pci_reserve= [PCI]
29 * Format: [<sbdf>[+IO<size>][+MEM<size>]][,<sbdf>...]
30 * Format of sbdf: [<segment>:]<bus>:<dev>.<func>
31 */
32 static int pci_reserve_parse_size(const char *str,
33 unsigned long *io_size,
34 unsigned long *mem_size)
35 {
36 if (sscanf(str, "io%lx", io_size) == 1 ||
37 sscanf(str, "IO%lx", io_size) == 1)
38 return 0;
40 if (sscanf(str, "mem%lx", mem_size) == 1 ||
41 sscanf(str, "MEM%lx", mem_size) == 1)
42 return 0;
44 return -EINVAL;
45 }
47 static int pci_reserve_parse_one(const char *str,
48 int *seg, int *bus, int *dev, int *func,
49 unsigned long *io_size,
50 unsigned long *mem_size)
51 {
52 char *p;
54 *io_size = 0;
55 *mem_size = 0;
57 if (sscanf(str, "%x:%x:%x.%x", seg, bus, dev, func) != 4) {
58 *seg = 0;
59 if (sscanf(str, "%x:%x.%x", bus, dev, func) != 3) {
60 return -EINVAL;
61 }
62 }
64 p = strchr(str, '+');
65 if (p == NULL)
66 return -EINVAL;
67 p++;
68 if (pci_reserve_parse_size(p, io_size, mem_size))
69 return -EINVAL;
71 p = strchr(str, '+');
72 if (p != NULL) {
73 p++;
74 pci_reserve_parse_size(p, io_size, mem_size);
75 }
76 return 0;
77 }
79 static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags)
80 {
81 char *sp;
82 char *ep;
84 int seg;
85 int bus;
86 int dev;
87 int func;
89 unsigned long io_size;
90 unsigned long mem_size;
92 sp = pci_reserve_param;
94 do {
95 ep = strchr(sp, ',');
96 if (ep)
97 *ep = '\0'; /* chomp */
99 if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func,
100 &io_size, &mem_size) == 0) {
101 if (pci_domain_nr(pbus) == seg &&
102 pbus->number == bus &&
103 PCI_SLOT(pbus->self->devfn) == dev &&
104 PCI_FUNC(pbus->self->devfn) == func) {
105 switch (flags) {
106 case IORESOURCE_IO:
107 return io_size;
108 case IORESOURCE_MEM:
109 return mem_size;
110 default:
111 break;
112 }
113 }
114 }
116 if (ep) {
117 *ep = ','; /* restore chomp'ed ',' for later */
118 ep++;
119 }
120 sp = ep;
121 } while (ep);
123 return 0;
124 }
126 unsigned long pci_reserve_size_io(struct pci_bus *pbus)
127 {
128 return pci_reserve_size(pbus, IORESOURCE_IO);
129 }
131 unsigned long pci_reserve_size_mem(struct pci_bus *pbus)
132 {
133 return pci_reserve_size(pbus, IORESOURCE_MEM);
134 }
136 static int __init pci_reserve_setup(char *str)
137 {
138 if (strlen(str) >= sizeof(pci_reserve_param))
139 return 0;
140 strlcpy(pci_reserve_param, str, sizeof(pci_reserve_param));
141 return 1;
142 }
143 __setup("pci_reserve=", pci_reserve_setup);