ia64/linux-2.6.18-xen.hg

view drivers/mtd/redboot.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: redboot.c,v 1.21 2006/03/30 18:34:37 bjd Exp $
3 *
4 * Parse RedBoot-style Flash Image System (FIS) tables and
5 * produce a Linux partition array to match.
6 */
8 #include <linux/kernel.h>
9 #include <linux/slab.h>
10 #include <linux/init.h>
11 #include <linux/vmalloc.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/partitions.h>
16 struct fis_image_desc {
17 unsigned char name[16]; // Null terminated name
18 uint32_t flash_base; // Address within FLASH of image
19 uint32_t mem_base; // Address in memory where it executes
20 uint32_t size; // Length of image
21 uint32_t entry_point; // Execution entry point
22 uint32_t data_length; // Length of actual data
23 unsigned char _pad[256-(16+7*sizeof(uint32_t))];
24 uint32_t desc_cksum; // Checksum over image descriptor
25 uint32_t file_cksum; // Checksum over image data
26 };
28 struct fis_list {
29 struct fis_image_desc *img;
30 struct fis_list *next;
31 };
33 static int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK;
34 module_param(directory, int, 0);
36 static inline int redboot_checksum(struct fis_image_desc *img)
37 {
38 /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */
39 return 1;
40 }
42 static int parse_redboot_partitions(struct mtd_info *master,
43 struct mtd_partition **pparts,
44 unsigned long fis_origin)
45 {
46 int nrparts = 0;
47 struct fis_image_desc *buf;
48 struct mtd_partition *parts;
49 struct fis_list *fl = NULL, *tmp_fl;
50 int ret, i;
51 size_t retlen;
52 char *names;
53 char *nullname;
54 int namelen = 0;
55 int nulllen = 0;
56 int numslots;
57 unsigned long offset;
58 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
59 static char nullstring[] = "unallocated";
60 #endif
62 buf = vmalloc(master->erasesize);
64 if (!buf)
65 return -ENOMEM;
67 if ( directory < 0 )
68 offset = master->size + directory*master->erasesize;
69 else
70 offset = directory*master->erasesize;
72 printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n",
73 master->name, offset);
75 ret = master->read(master, offset,
76 master->erasesize, &retlen, (void *)buf);
78 if (ret)
79 goto out;
81 if (retlen != master->erasesize) {
82 ret = -EIO;
83 goto out;
84 }
86 numslots = (master->erasesize / sizeof(struct fis_image_desc));
87 for (i = 0; i < numslots; i++) {
88 if (!memcmp(buf[i].name, "FIS directory", 14)) {
89 /* This is apparently the FIS directory entry for the
90 * FIS directory itself. The FIS directory size is
91 * one erase block; if the buf[i].size field is
92 * swab32(erasesize) then we know we are looking at
93 * a byte swapped FIS directory - swap all the entries!
94 * (NOTE: this is 'size' not 'data_length'; size is
95 * the full size of the entry.)
96 */
97 if (swab32(buf[i].size) == master->erasesize) {
98 int j;
99 for (j = 0; j < numslots && buf[j].name[0] != 0xff; ++j) {
100 /* The unsigned long fields were written with the
101 * wrong byte sex, name and pad have no byte sex.
102 */
103 swab32s(&buf[j].flash_base);
104 swab32s(&buf[j].mem_base);
105 swab32s(&buf[j].size);
106 swab32s(&buf[j].entry_point);
107 swab32s(&buf[j].data_length);
108 swab32s(&buf[j].desc_cksum);
109 swab32s(&buf[j].file_cksum);
110 }
111 }
112 break;
113 }
114 }
115 if (i == numslots) {
116 /* Didn't find it */
117 printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
118 master->name);
119 ret = 0;
120 goto out;
121 }
123 for (i = 0; i < numslots; i++) {
124 struct fis_list *new_fl, **prev;
126 if (buf[i].name[0] == 0xff)
127 continue;
128 if (!redboot_checksum(&buf[i]))
129 break;
131 new_fl = kmalloc(sizeof(struct fis_list), GFP_KERNEL);
132 namelen += strlen(buf[i].name)+1;
133 if (!new_fl) {
134 ret = -ENOMEM;
135 goto out;
136 }
137 new_fl->img = &buf[i];
138 if (fis_origin) {
139 buf[i].flash_base -= fis_origin;
140 } else {
141 buf[i].flash_base &= master->size-1;
142 }
144 /* I'm sure the JFFS2 code has done me permanent damage.
145 * I now think the following is _normal_
146 */
147 prev = &fl;
148 while(*prev && (*prev)->img->flash_base < new_fl->img->flash_base)
149 prev = &(*prev)->next;
150 new_fl->next = *prev;
151 *prev = new_fl;
153 nrparts++;
154 }
155 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
156 if (fl->img->flash_base) {
157 nrparts++;
158 nulllen = sizeof(nullstring);
159 }
161 for (tmp_fl = fl; tmp_fl->next; tmp_fl = tmp_fl->next) {
162 if (tmp_fl->img->flash_base + tmp_fl->img->size + master->erasesize <= tmp_fl->next->img->flash_base) {
163 nrparts++;
164 nulllen = sizeof(nullstring);
165 }
166 }
167 #endif
168 parts = kmalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
170 if (!parts) {
171 ret = -ENOMEM;
172 goto out;
173 }
175 memset(parts, 0, sizeof(*parts)*nrparts + nulllen + namelen);
177 nullname = (char *)&parts[nrparts];
178 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
179 if (nulllen > 0) {
180 strcpy(nullname, nullstring);
181 }
182 #endif
183 names = nullname + nulllen;
185 i=0;
187 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
188 if (fl->img->flash_base) {
189 parts[0].name = nullname;
190 parts[0].size = fl->img->flash_base;
191 parts[0].offset = 0;
192 i++;
193 }
194 #endif
195 for ( ; i<nrparts; i++) {
196 parts[i].size = fl->img->size;
197 parts[i].offset = fl->img->flash_base;
198 parts[i].name = names;
200 strcpy(names, fl->img->name);
201 #ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY
202 if (!memcmp(names, "RedBoot", 8) ||
203 !memcmp(names, "RedBoot config", 15) ||
204 !memcmp(names, "FIS directory", 14)) {
205 parts[i].mask_flags = MTD_WRITEABLE;
206 }
207 #endif
208 names += strlen(names)+1;
210 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
211 if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
212 i++;
213 parts[i].offset = parts[i-1].size + parts[i-1].offset;
214 parts[i].size = fl->next->img->flash_base - parts[i].offset;
215 parts[i].name = nullname;
216 }
217 #endif
218 tmp_fl = fl;
219 fl = fl->next;
220 kfree(tmp_fl);
221 }
222 ret = nrparts;
223 *pparts = parts;
224 out:
225 while (fl) {
226 struct fis_list *old = fl;
227 fl = fl->next;
228 kfree(old);
229 }
230 vfree(buf);
231 return ret;
232 }
234 static struct mtd_part_parser redboot_parser = {
235 .owner = THIS_MODULE,
236 .parse_fn = parse_redboot_partitions,
237 .name = "RedBoot",
238 };
240 static int __init redboot_parser_init(void)
241 {
242 return register_mtd_parser(&redboot_parser);
243 }
245 static void __exit redboot_parser_exit(void)
246 {
247 deregister_mtd_parser(&redboot_parser);
248 }
250 module_init(redboot_parser_init);
251 module_exit(redboot_parser_exit);
253 MODULE_LICENSE("GPL");
254 MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
255 MODULE_DESCRIPTION("Parsing code for RedBoot Flash Image System (FIS) tables");