ia64/linux-2.6.18-xen.hg

view drivers/mtd/cmdlinepart.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
line source
1 /*
2 * $Id: cmdlinepart.c,v 1.19 2005/11/07 11:14:19 gleixner Exp $
3 *
4 * Read flash partition table from command line
5 *
6 * Copyright 2002 SYSGO Real-Time Solutions GmbH
7 *
8 * The format for the command line is as follows:
9 *
10 * mtdparts=<mtddef>[;<mtddef]
11 * <mtddef> := <mtd-id>:<partdef>[,<partdef>]
12 * <partdef> := <size>[@offset][<name>][ro]
13 * <mtd-id> := unique name used in mapping driver/device (mtd->name)
14 * <size> := standard linux memsize OR "-" to denote all remaining space
15 * <name> := '(' NAME ')'
16 *
17 * Examples:
18 *
19 * 1 NOR Flash, with 1 single writable partition:
20 * edb7312-nor:-
21 *
22 * 1 NOR Flash with 2 partitions, 1 NAND with one
23 * edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
24 */
26 #include <linux/kernel.h>
27 #include <linux/slab.h>
29 #include <linux/mtd/mtd.h>
30 #include <linux/mtd/partitions.h>
31 #include <linux/bootmem.h>
33 /* error message prefix */
34 #define ERRP "mtd: "
36 /* debug macro */
37 #if 0
38 #define dbg(x) do { printk("DEBUG-CMDLINE-PART: "); printk x; } while(0)
39 #else
40 #define dbg(x)
41 #endif
44 /* special size referring to all the remaining space in a partition */
45 #define SIZE_REMAINING UINT_MAX
46 #define OFFSET_CONTINUOUS UINT_MAX
48 struct cmdline_mtd_partition {
49 struct cmdline_mtd_partition *next;
50 char *mtd_id;
51 int num_parts;
52 struct mtd_partition *parts;
53 };
55 /* mtdpart_setup() parses into here */
56 static struct cmdline_mtd_partition *partitions;
58 /* the command line passed to mtdpart_setupd() */
59 static char *cmdline;
60 static int cmdline_parsed = 0;
62 /*
63 * Parse one partition definition for an MTD. Since there can be many
64 * comma separated partition definitions, this function calls itself
65 * recursively until no more partition definitions are found. Nice side
66 * effect: the memory to keep the mtd_partition structs and the names
67 * is allocated upon the last definition being found. At that point the
68 * syntax has been verified ok.
69 */
70 static struct mtd_partition * newpart(char *s,
71 char **retptr,
72 int *num_parts,
73 int this_part,
74 unsigned char **extra_mem_ptr,
75 int extra_mem_size)
76 {
77 struct mtd_partition *parts;
78 unsigned long size;
79 unsigned long offset = OFFSET_CONTINUOUS;
80 char *name;
81 int name_len;
82 unsigned char *extra_mem;
83 char delim;
84 unsigned int mask_flags;
86 /* fetch the partition size */
87 if (*s == '-')
88 { /* assign all remaining space to this partition */
89 size = SIZE_REMAINING;
90 s++;
91 }
92 else
93 {
94 size = memparse(s, &s);
95 if (size < PAGE_SIZE)
96 {
97 printk(KERN_ERR ERRP "partition size too small (%lx)\n", size);
98 return NULL;
99 }
100 }
102 /* fetch partition name and flags */
103 mask_flags = 0; /* this is going to be a regular partition */
104 delim = 0;
105 /* check for offset */
106 if (*s == '@')
107 {
108 s++;
109 offset = memparse(s, &s);
110 }
111 /* now look for name */
112 if (*s == '(')
113 {
114 delim = ')';
115 }
117 if (delim)
118 {
119 char *p;
121 name = ++s;
122 if ((p = strchr(name, delim)) == 0)
123 {
124 printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim);
125 return NULL;
126 }
127 name_len = p - name;
128 s = p + 1;
129 }
130 else
131 {
132 name = NULL;
133 name_len = 13; /* Partition_000 */
134 }
136 /* record name length for memory allocation later */
137 extra_mem_size += name_len + 1;
139 /* test for options */
140 if (strncmp(s, "ro", 2) == 0)
141 {
142 mask_flags |= MTD_WRITEABLE;
143 s += 2;
144 }
146 /* test if more partitions are following */
147 if (*s == ',')
148 {
149 if (size == SIZE_REMAINING)
150 {
151 printk(KERN_ERR ERRP "no partitions allowed after a fill-up partition\n");
152 return NULL;
153 }
154 /* more partitions follow, parse them */
155 if ((parts = newpart(s + 1, &s, num_parts,
156 this_part + 1, &extra_mem, extra_mem_size)) == 0)
157 return NULL;
158 }
159 else
160 { /* this is the last partition: allocate space for all */
161 int alloc_size;
163 *num_parts = this_part + 1;
164 alloc_size = *num_parts * sizeof(struct mtd_partition) +
165 extra_mem_size;
166 parts = kmalloc(alloc_size, GFP_KERNEL);
167 if (!parts)
168 {
169 printk(KERN_ERR ERRP "out of memory\n");
170 return NULL;
171 }
172 memset(parts, 0, alloc_size);
173 extra_mem = (unsigned char *)(parts + *num_parts);
174 }
175 /* enter this partition (offset will be calculated later if it is zero at this point) */
176 parts[this_part].size = size;
177 parts[this_part].offset = offset;
178 parts[this_part].mask_flags = mask_flags;
179 if (name)
180 {
181 strlcpy(extra_mem, name, name_len + 1);
182 }
183 else
184 {
185 sprintf(extra_mem, "Partition_%03d", this_part);
186 }
187 parts[this_part].name = extra_mem;
188 extra_mem += name_len + 1;
190 dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n",
191 this_part,
192 parts[this_part].name,
193 parts[this_part].offset,
194 parts[this_part].size,
195 parts[this_part].mask_flags));
197 /* return (updated) pointer to extra_mem memory */
198 if (extra_mem_ptr)
199 *extra_mem_ptr = extra_mem;
201 /* return (updated) pointer command line string */
202 *retptr = s;
204 /* return partition table */
205 return parts;
206 }
208 /*
209 * Parse the command line.
210 */
211 static int mtdpart_setup_real(char *s)
212 {
213 cmdline_parsed = 1;
215 for( ; s != NULL; )
216 {
217 struct cmdline_mtd_partition *this_mtd;
218 struct mtd_partition *parts;
219 int mtd_id_len;
220 int num_parts;
221 char *p, *mtd_id;
223 mtd_id = s;
224 /* fetch <mtd-id> */
225 if (!(p = strchr(s, ':')))
226 {
227 printk(KERN_ERR ERRP "no mtd-id\n");
228 return 0;
229 }
230 mtd_id_len = p - mtd_id;
232 dbg(("parsing <%s>\n", p+1));
234 /*
235 * parse one mtd. have it reserve memory for the
236 * struct cmdline_mtd_partition and the mtd-id string.
237 */
238 parts = newpart(p + 1, /* cmdline */
239 &s, /* out: updated cmdline ptr */
240 &num_parts, /* out: number of parts */
241 0, /* first partition */
242 (unsigned char**)&this_mtd, /* out: extra mem */
243 mtd_id_len + 1 + sizeof(*this_mtd) +
244 sizeof(void*)-1 /*alignment*/);
245 if(!parts)
246 {
247 /*
248 * An error occurred. We're either:
249 * a) out of memory, or
250 * b) in the middle of the partition spec
251 * Either way, this mtd is hosed and we're
252 * unlikely to succeed in parsing any more
253 */
254 return 0;
255 }
257 /* align this_mtd */
258 this_mtd = (struct cmdline_mtd_partition *)
259 ALIGN((unsigned long)this_mtd, sizeof(void*));
260 /* enter results */
261 this_mtd->parts = parts;
262 this_mtd->num_parts = num_parts;
263 this_mtd->mtd_id = (char*)(this_mtd + 1);
264 strlcpy(this_mtd->mtd_id, mtd_id, mtd_id_len + 1);
266 /* link into chain */
267 this_mtd->next = partitions;
268 partitions = this_mtd;
270 dbg(("mtdid=<%s> num_parts=<%d>\n",
271 this_mtd->mtd_id, this_mtd->num_parts));
274 /* EOS - we're done */
275 if (*s == 0)
276 break;
278 /* does another spec follow? */
279 if (*s != ';')
280 {
281 printk(KERN_ERR ERRP "bad character after partition (%c)\n", *s);
282 return 0;
283 }
284 s++;
285 }
286 return 1;
287 }
289 /*
290 * Main function to be called from the MTD mapping driver/device to
291 * obtain the partitioning information. At this point the command line
292 * arguments will actually be parsed and turned to struct mtd_partition
293 * information. It returns partitions for the requested mtd device, or
294 * the first one in the chain if a NULL mtd_id is passed in.
295 */
296 static int parse_cmdline_partitions(struct mtd_info *master,
297 struct mtd_partition **pparts,
298 unsigned long origin)
299 {
300 unsigned long offset;
301 int i;
302 struct cmdline_mtd_partition *part;
303 char *mtd_id = master->name;
305 if(!cmdline)
306 return -EINVAL;
308 /* parse command line */
309 if (!cmdline_parsed)
310 mtdpart_setup_real(cmdline);
312 for(part = partitions; part; part = part->next)
313 {
314 if ((!mtd_id) || (!strcmp(part->mtd_id, mtd_id)))
315 {
316 for(i = 0, offset = 0; i < part->num_parts; i++)
317 {
318 if (part->parts[i].offset == OFFSET_CONTINUOUS)
319 part->parts[i].offset = offset;
320 else
321 offset = part->parts[i].offset;
322 if (part->parts[i].size == SIZE_REMAINING)
323 part->parts[i].size = master->size - offset;
324 if (offset + part->parts[i].size > master->size)
325 {
326 printk(KERN_WARNING ERRP
327 "%s: partitioning exceeds flash size, truncating\n",
328 part->mtd_id);
329 part->parts[i].size = master->size - offset;
330 part->num_parts = i;
331 }
332 offset += part->parts[i].size;
333 }
334 *pparts = part->parts;
335 return part->num_parts;
336 }
337 }
338 return -EINVAL;
339 }
342 /*
343 * This is the handler for our kernel parameter, called from
344 * main.c::checksetup(). Note that we can not yet kmalloc() anything,
345 * so we only save the commandline for later processing.
346 *
347 * This function needs to be visible for bootloaders.
348 */
349 int mtdpart_setup(char *s)
350 {
351 cmdline = s;
352 return 1;
353 }
355 __setup("mtdparts=", mtdpart_setup);
357 static struct mtd_part_parser cmdline_parser = {
358 .owner = THIS_MODULE,
359 .parse_fn = parse_cmdline_partitions,
360 .name = "cmdlinepart",
361 };
363 static int __init cmdline_parser_init(void)
364 {
365 return register_mtd_parser(&cmdline_parser);
366 }
368 module_init(cmdline_parser_init);
370 MODULE_LICENSE("GPL");
371 MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
372 MODULE_DESCRIPTION("Command line configuration of MTD partitions");