ia64/linux-2.6.18-xen.hg

view arch/mips/basler/excite/excite_iodev.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 * Copyright (C) 2005 by Basler Vision Technologies AG
3 * Author: Thomas Koeller <thomas.koeller@baslerweb.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
20 #include <linux/compiler.h>
21 #include <linux/init.h>
22 #include <linux/module.h>
23 #include <linux/sched.h>
24 #include <linux/wait.h>
25 #include <linux/poll.h>
26 #include <linux/interrupt.h>
27 #include <linux/platform_device.h>
28 #include <linux/miscdevice.h>
30 #include "excite_iodev.h"
34 static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
35 static int __init iodev_probe(struct device *);
36 static int __exit iodev_remove(struct device *);
37 static int iodev_open(struct inode *, struct file *);
38 static int iodev_release(struct inode *, struct file *);
39 static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
40 static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
41 static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *);
45 static const char iodev_name[] = "iodev";
46 static unsigned int iodev_irq;
47 static DECLARE_WAIT_QUEUE_HEAD(wq);
51 static struct file_operations fops =
52 {
53 .owner = THIS_MODULE,
54 .open = iodev_open,
55 .release = iodev_release,
56 .read = iodev_read,
57 .poll = iodev_poll
58 };
60 static struct miscdevice miscdev =
61 {
62 .minor = MISC_DYNAMIC_MINOR,
63 .name = iodev_name,
64 .fops = &fops
65 };
67 static struct device_driver iodev_driver =
68 {
69 .name = (char *) iodev_name,
70 .bus = &platform_bus_type,
71 .owner = THIS_MODULE,
72 .probe = iodev_probe,
73 .remove = __exit_p(iodev_remove)
74 };
78 static const struct resource *
79 iodev_get_resource(struct platform_device *pdv, const char *name,
80 unsigned int type)
81 {
82 char buf[80];
83 if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
84 return NULL;
85 return platform_get_resource_byname(pdv, type, buf);
86 }
90 /* No hotplugging on the platform bus - use __init */
91 static int __init iodev_probe(struct device *dev)
92 {
93 struct platform_device * const pdv = to_platform_device(dev);
94 const struct resource * const ri =
95 iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
97 if (unlikely(!ri))
98 return -ENXIO;
100 iodev_irq = ri->start;
101 return misc_register(&miscdev);
102 }
106 static int __exit iodev_remove(struct device *dev)
107 {
108 return misc_deregister(&miscdev);
109 }
113 static int iodev_open(struct inode *i, struct file *f)
114 {
115 return request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED,
116 iodev_name, &miscdev);
117 }
121 static int iodev_release(struct inode *i, struct file *f)
122 {
123 free_irq(iodev_irq, &miscdev);
124 return 0;
125 }
130 static ssize_t
131 iodev_read(struct file *f, char __user *d, size_t s, loff_t *o)
132 {
133 ssize_t ret;
134 DEFINE_WAIT(w);
136 prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE);
137 if (!signal_pending(current))
138 schedule();
139 ret = signal_pending(current) ? -ERESTARTSYS : 0;
140 finish_wait(&wq, &w);
141 return ret;
142 }
145 static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p)
146 {
147 poll_wait(f, &wq, p);
148 return POLLOUT | POLLWRNORM;
149 }
154 static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
155 {
156 wake_up(&wq);
157 return IRQ_HANDLED;
158 }
162 static int __init iodev_init_module(void)
163 {
164 return driver_register(&iodev_driver);
165 }
169 static void __exit iodev_cleanup_module(void)
170 {
171 driver_unregister(&iodev_driver);
172 }
174 module_init(iodev_init_module);
175 module_exit(iodev_cleanup_module);
179 MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
180 MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler");
181 MODULE_VERSION("0.0");
182 MODULE_LICENSE("GPL");