diff options
Diffstat (limited to 'drivers/xen/balloon.c')
-rw-r--r-- | drivers/xen/balloon.c | 41 |
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 | ||
182 | static unsigned long current_target(void) | 187 | static 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 | ||
271 | static int decrease_reservation(unsigned long nr_pages) | 262 | static 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) | |||
367 | static void balloon_set_new_target(unsigned long target) | 357 | static 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); | |||
472 | BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); | 459 | BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages)); |
473 | BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); | 460 | BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low)); |
474 | BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); | 461 | BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high)); |
475 | BALLOON_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); | ||
478 | BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); | 462 | BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages)); |
479 | 463 | ||
480 | static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr, | 464 | static 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 | }; |