aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/balloon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/balloon.c')
-rw-r--r--drivers/xen/balloon.c41
1 files changed, 12 insertions, 29 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index d31505b6f7a4..1a0d8c2a0354 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -43,6 +43,7 @@
43#include <linux/mutex.h> 43#include <linux/mutex.h>
44#include <linux/list.h> 44#include <linux/list.h>
45#include <linux/sysdev.h> 45#include <linux/sysdev.h>
46#include <linux/gfp.h>
46 47
47#include <asm/page.h> 48#include <asm/page.h>
48#include <asm/pgalloc.h> 49#include <asm/pgalloc.h>
@@ -52,6 +53,8 @@
52 53
53#include <asm/xen/hypervisor.h> 54#include <asm/xen/hypervisor.h>
54#include <asm/xen/hypercall.h> 55#include <asm/xen/hypercall.h>
56
57#include <xen/xen.h>
55#include <xen/interface/xen.h> 58#include <xen/interface/xen.h>
56#include <xen/interface/memory.h> 59#include <xen/interface/memory.h>
57#include <xen/xenbus.h> 60#include <xen/xenbus.h>
@@ -66,8 +69,6 @@ struct balloon_stats {
66 /* We aim for 'current allocation' == 'target allocation'. */ 69 /* We aim for 'current allocation' == 'target allocation'. */
67 unsigned long current_pages; 70 unsigned long current_pages;
68 unsigned long target_pages; 71 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 /* 72 /*
72 * Drivers may alter the memory reservation independently, but they 73 * Drivers may alter the memory reservation independently, but they
73 * must inform the balloon driver so we avoid hitting the hard limit. 74 * must inform the balloon driver so we avoid hitting the hard limit.
@@ -136,6 +137,8 @@ static void balloon_append(struct page *page)
136 list_add(&page->lru, &ballooned_pages); 137 list_add(&page->lru, &ballooned_pages);
137 balloon_stats.balloon_low++; 138 balloon_stats.balloon_low++;
138 } 139 }
140
141 totalram_pages--;
139} 142}
140 143
141/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ 144/* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
@@ -156,6 +159,8 @@ static struct page *balloon_retrieve(void)
156 else 159 else
157 balloon_stats.balloon_low--; 160 balloon_stats.balloon_low--;
158 161
162 totalram_pages++;
163
159 return page; 164 return page;
160} 165}
161 166
@@ -181,7 +186,7 @@ static void balloon_alarm(unsigned long unused)
181 186
182static unsigned long current_target(void) 187static unsigned long current_target(void)
183{ 188{
184 unsigned long target = min(balloon_stats.target_pages, balloon_stats.hard_limit); 189 unsigned long target = balloon_stats.target_pages;
185 190
186 target = min(target, 191 target = min(target,
187 balloon_stats.current_pages + 192 balloon_stats.current_pages +
@@ -217,23 +222,10 @@ static int increase_reservation(unsigned long nr_pages)
217 set_xen_guest_handle(reservation.extent_start, frame_list); 222 set_xen_guest_handle(reservation.extent_start, frame_list);
218 reservation.nr_extents = nr_pages; 223 reservation.nr_extents = nr_pages;
219 rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation); 224 rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
220 if (rc < nr_pages) { 225 if (rc < 0)
221 if (rc > 0) {
222 int ret;
223
224 /* We hit the Xen hard limit: reprobe. */
225 reservation.nr_extents = rc;
226 ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
227 &reservation);
228 BUG_ON(ret != rc);
229 }
230 if (rc >= 0)
231 balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
232 balloon_stats.driver_pages);
233 goto out; 226 goto out;
234 }
235 227
236 for (i = 0; i < nr_pages; i++) { 228 for (i = 0; i < rc; i++) {
237 page = balloon_retrieve(); 229 page = balloon_retrieve();
238 BUG_ON(page == NULL); 230 BUG_ON(page == NULL);
239 231
@@ -259,13 +251,12 @@ static int increase_reservation(unsigned long nr_pages)
259 __free_page(page); 251 __free_page(page);
260 } 252 }
261 253
262 balloon_stats.current_pages += nr_pages; 254 balloon_stats.current_pages += rc;
263 totalram_pages = balloon_stats.current_pages;
264 255
265 out: 256 out:
266 spin_unlock_irqrestore(&balloon_lock, flags); 257 spin_unlock_irqrestore(&balloon_lock, flags);
267 258
268 return 0; 259 return rc < 0 ? rc : rc != nr_pages;
269} 260}
270 261
271static int decrease_reservation(unsigned long nr_pages) 262static int decrease_reservation(unsigned long nr_pages)
@@ -323,7 +314,6 @@ static int decrease_reservation(unsigned long nr_pages)
323 BUG_ON(ret != nr_pages); 314 BUG_ON(ret != nr_pages);
324 315
325 balloon_stats.current_pages -= nr_pages; 316 balloon_stats.current_pages -= nr_pages;
326 totalram_pages = balloon_stats.current_pages;
327 317
328 spin_unlock_irqrestore(&balloon_lock, flags); 318 spin_unlock_irqrestore(&balloon_lock, flags);
329 319
@@ -367,7 +357,6 @@ static void balloon_process(struct work_struct *work)
367static void balloon_set_new_target(unsigned long target) 357static void balloon_set_new_target(unsigned long target)
368{ 358{
369 /* No need for lock. Not read-modify-write updates. */ 359 /* No need for lock. Not read-modify-write updates. */
370 balloon_stats.hard_limit = ~0UL;
371 balloon_stats.target_pages = target; 360 balloon_stats.target_pages = target;
372 schedule_work(&balloon_worker); 361 schedule_work(&balloon_worker);
373} 362}
@@ -422,12 +411,10 @@ static int __init balloon_init(void)
422 pr_info("xen_balloon: Initialising balloon driver.\n"); 411 pr_info("xen_balloon: Initialising balloon driver.\n");
423 412
424 balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn); 413 balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
425 totalram_pages = balloon_stats.current_pages;
426 balloon_stats.target_pages = balloon_stats.current_pages; 414 balloon_stats.target_pages = balloon_stats.current_pages;
427 balloon_stats.balloon_low = 0; 415 balloon_stats.balloon_low = 0;
428 balloon_stats.balloon_high = 0; 416 balloon_stats.balloon_high = 0;
429 balloon_stats.driver_pages = 0UL; 417 balloon_stats.driver_pages = 0UL;
430 balloon_stats.hard_limit = ~0UL;
431 418
432 init_timer(&balloon_timer); 419 init_timer(&balloon_timer);
433 balloon_timer.data = 0; 420 balloon_timer.data = 0;
@@ -472,9 +459,6 @@ module_exit(balloon_exit);
472BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); 459BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
473BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); 460BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
474BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); 461BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
475BALLOON_SHOW(hard_limit_kb,
476 (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
477 (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
478BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); 462BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
479 463
480static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, 464static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
@@ -544,7 +528,6 @@ static struct attribute *balloon_info_attrs[] = {
544 &attr_current_kb.attr, 528 &attr_current_kb.attr,
545 &attr_low_kb.attr, 529 &attr_low_kb.attr,
546 &attr_high_kb.attr, 530 &attr_high_kb.attr,
547 &attr_hard_limit_kb.attr,
548 &attr_driver_kb.attr, 531 &attr_driver_kb.attr,
549 NULL 532 NULL
550}; 533};