aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2009-06-05 06:58:37 -0400
committerJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>2009-12-04 11:15:19 -0500
commitbc2c0303226ec716854d3c208c7f84fe7aa35cd7 (patch)
treec4ae7635426fbf71ca1044bb72f0c5f5c3ea7acc
parent3d65c9488cadd2f11bd4d60c7266e639ece5d0d6 (diff)
xen: 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> Cc: Stable Kernel <stable@kernel.org>
-rw-r--r--drivers/xen/balloon.c31
1 files changed, 5 insertions, 26 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 6eb62654410a..420433613584 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -66,8 +66,6 @@ struct balloon_stats {
66 /* We aim for 'current allocation' == 'target allocation'. */ 66 /* We aim for 'current allocation' == 'target allocation'. */
67 unsigned long current_pages; 67 unsigned long current_pages;
68 unsigned long target_pages; 68 unsigned long target_pages;
69 /* We may hit the hard limit in Xen. If we do then we remember it. */
70 unsigned long hard_limit;
71 /* 69 /*
72 * Drivers may alter the memory reservation independently, but they 70 * Drivers may alter the memory reservation independently, but they
73 * must inform the balloon driver so we avoid hitting the hard limit. 71 * must inform the balloon driver so we avoid hitting the hard limit.
@@ -185,7 +183,7 @@ static void balloon_alarm(unsigned long unused)
185 183
186static unsigned long current_target(void) 184static unsigned long current_target(void)
187{ 185{
188 unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit); 186 unsigned long target = balloon_stats.target_pages;
189 187
190 target = min(target, 188 target = min(target,
191 balloon_stats.current_pages + 189 balloon_stats.current_pages +
@@ -221,23 +219,10 @@ static int increase_reservation(unsigned long nr_pages)
221 set_xen_guest_handle(reservation.extent_start, frame_list); 219 set_xen_guest_handle(reservation.extent_start, frame_list);
222 reservation.nr_extents = nr_pages; 220 reservation.nr_extents = nr_pages;
223 rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); 221 rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
224 if (rc < nr_pages) { 222 if (rc < 0)
225 if (rc > 0) {
226 int ret;
227
228 /* We hit the Xen hard limit: reprobe. */
229 reservation.nr_extents = rc;
230 ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
231 &reservation);
232 BUG_ON(ret != rc);
233 }
234 if (rc >= 0)
235 balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
236 balloon_stats.driver_pages);
237 goto out; 223 goto out;
238 }
239 224
240 for (i = 0; i < nr_pages; i++) { 225 for (i = 0; i < rc; i++) {
241 page = balloon_retrieve(); 226 page = balloon_retrieve();
242 BUG_ON(page == NULL); 227 BUG_ON(page == NULL);
243 228
@@ -263,12 +248,12 @@ static int increase_reservation(unsigned long nr_pages)
263 __free_page(page); 248 __free_page(page);
264 } 249 }
265 250
266 balloon_stats.current_pages += nr_pages; 251 balloon_stats.current_pages += rc;
267 252
268 out: 253 out:
269 spin_unlock_irqrestore(&balloon_lock, flags); 254 spin_unlock_irqrestore(&balloon_lock, flags);
270 255
271 return 0; 256 return rc < 0 ? rc : rc != nr_pages;
272} 257}
273 258
274static int decrease_reservation(unsigned long nr_pages) 259static int decrease_reservation(unsigned long nr_pages)
@@ -369,7 +354,6 @@ static void balloon_process(struct work_struct *work)
369static void balloon_set_new_target(unsigned long target) 354static void balloon_set_new_target(unsigned long target)
370{ 355{
371 /* No need for lock. Not read-modify-write updates. */ 356 /* No need for lock. Not read-modify-write updates. */
372 balloon_stats.hard_limit = ~0UL;
373 balloon_stats.target_pages = target; 357 balloon_stats.target_pages = target;
374 schedule_work(&balloon_worker); 358 schedule_work(&balloon_worker);
375} 359}
@@ -428,7 +412,6 @@ static int __init balloon_init(void)
428 balloon_stats.balloon_low = 0; 412 balloon_stats.balloon_low = 0;
429 balloon_stats.balloon_high = 0; 413 balloon_stats.balloon_high = 0;
430 balloon_stats.driver_pages = 0UL; 414 balloon_stats.driver_pages = 0UL;
431 balloon_stats.hard_limit = ~0UL;
432 415
433 init_timer(&balloon_timer); 416 init_timer(&balloon_timer);
434 balloon_timer.data = 0; 417 balloon_timer.data = 0;
@@ -473,9 +456,6 @@ module_exit(balloon_exit);
473BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); 456BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
474BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); 457BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
475BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); 458BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
476BALLOON_SHOW(hard_limit_kb,
477 (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
478 (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
479BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); 459BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
480 460
481static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, 461static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
@@ -545,7 +525,6 @@ static struct attribute *balloon_info_attrs[] = {
545 &attr_current_kb.attr, 525 &attr_current_kb.attr,
546 &attr_low_kb.attr, 526 &attr_low_kb.attr,
547 &attr_high_kb.attr, 527 &attr_high_kb.attr,
548 &attr_hard_limit_kb.attr,
549 &attr_driver_kb.attr, 528 &attr_driver_kb.attr,
550 NULL 529 NULL
551}; 530};