ia64/linux-2.6.18-xen.hg

view drivers/mtd/afs.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 /*======================================================================
3 drivers/mtd/afs.c: ARM Flash Layout/Partitioning
5 Copyright (C) 2000 ARM Limited
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 This is access code for flashes using ARM's flash partitioning
22 standards.
24 $Id: afs.c,v 1.15 2005/11/07 11:14:19 gleixner Exp $
26 ======================================================================*/
28 #include <linux/module.h>
29 #include <linux/types.h>
30 #include <linux/kernel.h>
31 #include <linux/slab.h>
32 #include <linux/string.h>
33 #include <linux/init.h>
35 #include <linux/mtd/mtd.h>
36 #include <linux/mtd/map.h>
37 #include <linux/mtd/partitions.h>
39 struct footer_struct {
40 u32 image_info_base; /* Address of first word of ImageFooter */
41 u32 image_start; /* Start of area reserved by this footer */
42 u32 signature; /* 'Magic' number proves it's a footer */
43 u32 type; /* Area type: ARM Image, SIB, customer */
44 u32 checksum; /* Just this structure */
45 };
47 struct image_info_struct {
48 u32 bootFlags; /* Boot flags, compression etc. */
49 u32 imageNumber; /* Unique number, selects for boot etc. */
50 u32 loadAddress; /* Address program should be loaded to */
51 u32 length; /* Actual size of image */
52 u32 address; /* Image is executed from here */
53 char name[16]; /* Null terminated */
54 u32 headerBase; /* Flash Address of any stripped header */
55 u32 header_length; /* Length of header in memory */
56 u32 headerType; /* AIF, RLF, s-record etc. */
57 u32 checksum; /* Image checksum (inc. this struct) */
58 };
60 static u32 word_sum(void *words, int num)
61 {
62 u32 *p = words;
63 u32 sum = 0;
65 while (num--)
66 sum += *p++;
68 return sum;
69 }
71 static int
72 afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
73 u_int off, u_int mask)
74 {
75 struct footer_struct fs;
76 u_int ptr = off + mtd->erasesize - sizeof(fs);
77 size_t sz;
78 int ret;
80 ret = mtd->read(mtd, ptr, sizeof(fs), &sz, (u_char *) &fs);
81 if (ret >= 0 && sz != sizeof(fs))
82 ret = -EINVAL;
84 if (ret < 0) {
85 printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n",
86 ptr, ret);
87 return ret;
88 }
90 ret = 1;
92 /*
93 * Does it contain the magic number?
94 */
95 if (fs.signature != 0xa0ffff9f)
96 ret = 0;
98 /*
99 * Check the checksum.
100 */
101 if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff)
102 ret = 0;
104 /*
105 * Don't touch the SIB.
106 */
107 if (fs.type == 2)
108 ret = 0;
110 *iis_start = fs.image_info_base & mask;
111 *img_start = fs.image_start & mask;
113 /*
114 * Check the image info base. This can not
115 * be located after the footer structure.
116 */
117 if (*iis_start >= ptr)
118 ret = 0;
120 /*
121 * Check the start of this image. The image
122 * data can not be located after this block.
123 */
124 if (*img_start > off)
125 ret = 0;
127 return ret;
128 }
130 static int
131 afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
132 {
133 size_t sz;
134 int ret, i;
136 memset(iis, 0, sizeof(*iis));
137 ret = mtd->read(mtd, ptr, sizeof(*iis), &sz, (u_char *) iis);
138 if (ret < 0)
139 goto failed;
141 if (sz != sizeof(*iis)) {
142 ret = -EINVAL;
143 goto failed;
144 }
146 ret = 0;
148 /*
149 * Validate the name - it must be NUL terminated.
150 */
151 for (i = 0; i < sizeof(iis->name); i++)
152 if (iis->name[i] == '\0')
153 break;
155 if (i < sizeof(iis->name))
156 ret = 1;
158 return ret;
160 failed:
161 printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n",
162 ptr, ret);
163 return ret;
164 }
166 static int parse_afs_partitions(struct mtd_info *mtd,
167 struct mtd_partition **pparts,
168 unsigned long origin)
169 {
170 struct mtd_partition *parts;
171 u_int mask, off, idx, sz;
172 int ret = 0;
173 char *str;
175 /*
176 * This is the address mask; we use this to mask off out of
177 * range address bits.
178 */
179 mask = mtd->size - 1;
181 /*
182 * First, calculate the size of the array we need for the
183 * partition information. We include in this the size of
184 * the strings.
185 */
186 for (idx = off = sz = 0; off < mtd->size; off += mtd->erasesize) {
187 struct image_info_struct iis;
188 u_int iis_ptr, img_ptr;
190 ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask);
191 if (ret < 0)
192 break;
193 if (ret == 0)
194 continue;
196 ret = afs_read_iis(mtd, &iis, iis_ptr);
197 if (ret < 0)
198 break;
199 if (ret == 0)
200 continue;
202 sz += sizeof(struct mtd_partition);
203 sz += strlen(iis.name) + 1;
204 idx += 1;
205 }
207 if (!sz)
208 return ret;
210 parts = kmalloc(sz, GFP_KERNEL);
211 if (!parts)
212 return -ENOMEM;
214 memset(parts, 0, sz);
215 str = (char *)(parts + idx);
217 /*
218 * Identify the partitions
219 */
220 for (idx = off = 0; off < mtd->size; off += mtd->erasesize) {
221 struct image_info_struct iis;
222 u_int iis_ptr, img_ptr;
224 /* Read the footer. */
225 ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask);
226 if (ret < 0)
227 break;
228 if (ret == 0)
229 continue;
231 /* Read the image info block */
232 ret = afs_read_iis(mtd, &iis, iis_ptr);
233 if (ret < 0)
234 break;
235 if (ret == 0)
236 continue;
238 strcpy(str, iis.name);
240 parts[idx].name = str;
241 parts[idx].size = (iis.length + mtd->erasesize - 1) & ~(mtd->erasesize - 1);
242 parts[idx].offset = img_ptr;
243 parts[idx].mask_flags = 0;
245 printk(" mtd%d: at 0x%08x, %5dKB, %8u, %s\n",
246 idx, img_ptr, parts[idx].size / 1024,
247 iis.imageNumber, str);
249 idx += 1;
250 str = str + strlen(iis.name) + 1;
251 }
253 if (!idx) {
254 kfree(parts);
255 parts = NULL;
256 }
258 *pparts = parts;
259 return idx ? idx : ret;
260 }
262 static struct mtd_part_parser afs_parser = {
263 .owner = THIS_MODULE,
264 .parse_fn = parse_afs_partitions,
265 .name = "afs",
266 };
268 static int __init afs_parser_init(void)
269 {
270 return register_mtd_parser(&afs_parser);
271 }
273 static void __exit afs_parser_exit(void)
274 {
275 deregister_mtd_parser(&afs_parser);
276 }
278 module_init(afs_parser_init);
279 module_exit(afs_parser_exit);
282 MODULE_AUTHOR("ARM Ltd");
283 MODULE_DESCRIPTION("ARM Firmware Suite partition parser");
284 MODULE_LICENSE("GPL");