ia64/linux-2.6.18-xen.hg

view drivers/xen/balloon/sysfs.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 bf8b1ee634e2
children
line source
1 /******************************************************************************
2 * balloon/sysfs.c
3 *
4 * Xen balloon driver - sysfs interfaces.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation; or, when distributed
9 * separately from the Linux kernel or incorporated into other
10 * software packages, subject to the following license:
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
31 #include <linux/capability.h>
32 #include <linux/errno.h>
33 #include <linux/init.h>
34 #include <linux/stat.h>
35 #include <linux/string.h>
36 #include <linux/sysdev.h>
37 #include "common.h"
39 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
40 #include <xen/platform-compat.h>
41 #endif
43 #define BALLOON_CLASS_NAME "xen_memory"
45 #define BALLOON_SHOW(name, format, args...) \
46 static ssize_t show_##name(struct sys_device *dev, \
47 char *buf) \
48 { \
49 return sprintf(buf, format, ##args); \
50 } \
51 static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
53 BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(bs.current_pages));
54 BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(bs.balloon_low));
55 BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high));
56 BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages));
58 static ssize_t show_target_kb(struct sys_device *dev, char *buf)
59 {
60 return sprintf(buf, "%lu\n", PAGES2KB(bs.target_pages));
61 }
63 static ssize_t store_target_kb(struct sys_device *dev,
64 const char *buf,
65 size_t count)
66 {
67 char memstring[64], *endchar;
68 unsigned long long target_bytes;
70 if (!capable(CAP_SYS_ADMIN))
71 return -EPERM;
73 if (count <= 1)
74 return -EBADMSG; /* runt */
75 if (count > sizeof(memstring))
76 return -EFBIG; /* too long */
77 strcpy(memstring, buf);
79 target_bytes = memparse(memstring, &endchar);
80 balloon_set_new_target(target_bytes >> PAGE_SHIFT);
82 return count;
83 }
85 static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
86 show_target_kb, store_target_kb);
88 static struct sysdev_attribute *balloon_attrs[] = {
89 &attr_target_kb,
90 };
92 static struct attribute *balloon_info_attrs[] = {
93 &attr_current_kb.attr,
94 &attr_low_kb.attr,
95 &attr_high_kb.attr,
96 &attr_driver_kb.attr,
97 NULL
98 };
100 static struct attribute_group balloon_info_group = {
101 .name = "info",
102 .attrs = balloon_info_attrs,
103 };
105 static struct sysdev_class balloon_sysdev_class = {
106 set_kset_name(BALLOON_CLASS_NAME),
107 };
109 static struct sys_device balloon_sysdev;
111 static int __init register_balloon(struct sys_device *sysdev)
112 {
113 int i, error;
115 error = sysdev_class_register(&balloon_sysdev_class);
116 if (error)
117 return error;
119 sysdev->id = 0;
120 sysdev->cls = &balloon_sysdev_class;
122 error = sysdev_register(sysdev);
123 if (error) {
124 sysdev_class_unregister(&balloon_sysdev_class);
125 return error;
126 }
128 for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
129 error = sysdev_create_file(sysdev, balloon_attrs[i]);
130 if (error)
131 goto fail;
132 }
134 error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
135 if (error)
136 goto fail;
138 return 0;
140 fail:
141 while (--i >= 0)
142 sysdev_remove_file(sysdev, balloon_attrs[i]);
143 sysdev_unregister(sysdev);
144 sysdev_class_unregister(&balloon_sysdev_class);
145 return error;
146 }
148 static __exit void unregister_balloon(struct sys_device *sysdev)
149 {
150 int i;
152 sysfs_remove_group(&sysdev->kobj, &balloon_info_group);
153 for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++)
154 sysdev_remove_file(sysdev, balloon_attrs[i]);
155 sysdev_unregister(sysdev);
156 sysdev_class_unregister(&balloon_sysdev_class);
157 }
159 int __init balloon_sysfs_init(void)
160 {
161 return register_balloon(&balloon_sysdev);
162 }
164 void __exit balloon_sysfs_exit(void)
165 {
166 unregister_balloon(&balloon_sysdev);
167 }