ia64/linux-2.6.18-xen.hg

view drivers/mtd/maps/plat-ram.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 /* drivers/mtd/maps/plat-ram.c
2 *
3 * (c) 2004-2005 Simtec Electronics
4 * http://www.simtec.co.uk/products/SWLINUX/
5 * Ben Dooks <ben@simtec.co.uk>
6 *
7 * Generic platfrom device based RAM map
8 *
9 * $Id: plat-ram.c,v 1.7 2005/11/07 11:14:28 gleixner Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
26 #include <linux/module.h>
27 #include <linux/types.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/string.h>
31 #include <linux/ioport.h>
32 #include <linux/device.h>
33 #include <linux/slab.h>
34 #include <linux/platform_device.h>
36 #include <linux/mtd/mtd.h>
37 #include <linux/mtd/map.h>
38 #include <linux/mtd/partitions.h>
39 #include <linux/mtd/plat-ram.h>
41 #include <asm/io.h>
43 /* private structure for each mtd platform ram device created */
45 struct platram_info {
46 struct device *dev;
47 struct mtd_info *mtd;
48 struct map_info map;
49 struct mtd_partition *partitions;
50 struct resource *area;
51 struct platdata_mtd_ram *pdata;
52 };
54 /* to_platram_info()
55 *
56 * device private data to struct platram_info conversion
57 */
59 static inline struct platram_info *to_platram_info(struct platform_device *dev)
60 {
61 return (struct platram_info *)platform_get_drvdata(dev);
62 }
64 /* platram_setrw
65 *
66 * call the platform device's set rw/ro control
67 *
68 * to = 0 => read-only
69 * = 1 => read-write
70 */
72 static inline void platram_setrw(struct platram_info *info, int to)
73 {
74 if (info->pdata == NULL)
75 return;
77 if (info->pdata->set_rw != NULL)
78 (info->pdata->set_rw)(info->dev, to);
79 }
81 /* platram_remove
82 *
83 * called to remove the device from the driver's control
84 */
86 static int platram_remove(struct platform_device *pdev)
87 {
88 struct platram_info *info = to_platram_info(pdev);
90 platform_set_drvdata(pdev, NULL);
92 dev_dbg(&pdev->dev, "removing device\n");
94 if (info == NULL)
95 return 0;
97 if (info->mtd) {
98 #ifdef CONFIG_MTD_PARTITIONS
99 if (info->partitions) {
100 del_mtd_partitions(info->mtd);
101 kfree(info->partitions);
102 }
103 #endif
104 del_mtd_device(info->mtd);
105 map_destroy(info->mtd);
106 }
108 /* ensure ram is left read-only */
110 platram_setrw(info, PLATRAM_RO);
112 /* release resources */
114 if (info->area) {
115 release_resource(info->area);
116 kfree(info->area);
117 }
119 if (info->map.virt != NULL)
120 iounmap(info->map.virt);
122 kfree(info);
124 return 0;
125 }
127 /* platram_probe
128 *
129 * called from device drive system when a device matching our
130 * driver is found.
131 */
133 static int platram_probe(struct platform_device *pdev)
134 {
135 struct platdata_mtd_ram *pdata;
136 struct platram_info *info;
137 struct resource *res;
138 int err = 0;
140 dev_dbg(&pdev->dev, "probe entered\n");
142 if (pdev->dev.platform_data == NULL) {
143 dev_err(&pdev->dev, "no platform data supplied\n");
144 err = -ENOENT;
145 goto exit_error;
146 }
148 pdata = pdev->dev.platform_data;
150 info = kmalloc(sizeof(*info), GFP_KERNEL);
151 if (info == NULL) {
152 dev_err(&pdev->dev, "no memory for flash info\n");
153 err = -ENOMEM;
154 goto exit_error;
155 }
157 memset(info, 0, sizeof(*info));
158 platform_set_drvdata(pdev, info);
160 info->dev = &pdev->dev;
161 info->pdata = pdata;
163 /* get the resource for the memory mapping */
165 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
167 if (res == NULL) {
168 dev_err(&pdev->dev, "no memory resource specified\n");
169 err = -ENOENT;
170 goto exit_free;
171 }
173 dev_dbg(&pdev->dev, "got platform resource %p (0x%lx)\n", res, res->start);
175 /* setup map parameters */
177 info->map.phys = res->start;
178 info->map.size = (res->end - res->start) + 1;
179 info->map.name = pdata->mapname != NULL ? pdata->mapname : (char *)pdev->name;
180 info->map.bankwidth = pdata->bankwidth;
182 /* register our usage of the memory area */
184 info->area = request_mem_region(res->start, info->map.size, pdev->name);
185 if (info->area == NULL) {
186 dev_err(&pdev->dev, "failed to request memory region\n");
187 err = -EIO;
188 goto exit_free;
189 }
191 /* remap the memory area */
193 info->map.virt = ioremap(res->start, info->map.size);
194 dev_dbg(&pdev->dev, "virt %p, %lu bytes\n", info->map.virt, info->map.size);
196 if (info->map.virt == NULL) {
197 dev_err(&pdev->dev, "failed to ioremap() region\n");
198 err = -EIO;
199 goto exit_free;
200 }
202 simple_map_init(&info->map);
204 dev_dbg(&pdev->dev, "initialised map, probing for mtd\n");
206 /* probe for the right mtd map driver */
208 info->mtd = do_map_probe("map_ram" , &info->map);
209 if (info->mtd == NULL) {
210 dev_err(&pdev->dev, "failed to probe for map_ram\n");
211 err = -ENOMEM;
212 goto exit_free;
213 }
215 info->mtd->owner = THIS_MODULE;
217 platram_setrw(info, PLATRAM_RW);
219 /* check to see if there are any available partitions, or wether
220 * to add this device whole */
222 #ifdef CONFIG_MTD_PARTITIONS
223 if (pdata->nr_partitions > 0) {
224 const char **probes = { NULL };
226 if (pdata->probes)
227 probes = (const char **)pdata->probes;
229 err = parse_mtd_partitions(info->mtd, probes,
230 &info->partitions, 0);
231 if (err > 0) {
232 err = add_mtd_partitions(info->mtd, info->partitions,
233 err);
234 }
235 }
236 #endif /* CONFIG_MTD_PARTITIONS */
238 if (add_mtd_device(info->mtd)) {
239 dev_err(&pdev->dev, "add_mtd_device() failed\n");
240 err = -ENOMEM;
241 }
243 dev_info(&pdev->dev, "registered mtd device\n");
244 return err;
246 exit_free:
247 platram_remove(pdev);
248 exit_error:
249 return err;
250 }
252 /* device driver info */
254 static struct platform_driver platram_driver = {
255 .probe = platram_probe,
256 .remove = platram_remove,
257 .driver = {
258 .name = "mtd-ram",
259 .owner = THIS_MODULE,
260 },
261 };
263 /* module init/exit */
265 static int __init platram_init(void)
266 {
267 printk("Generic platform RAM MTD, (c) 2004 Simtec Electronics\n");
268 return platform_driver_register(&platram_driver);
269 }
271 static void __exit platram_exit(void)
272 {
273 platform_driver_unregister(&platram_driver);
274 }
276 module_init(platram_init);
277 module_exit(platram_exit);
279 MODULE_LICENSE("GPL");
280 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
281 MODULE_DESCRIPTION("MTD platform RAM map driver");