summaryrefslogtreecommitdiffstats
path: root/drivers/xen/balloon.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2015-06-25 11:29:18 -0400
committerDavid Vrabel <david.vrabel@citrix.com>2015-10-23 09:20:05 -0400
commit1cf6a6c82918c9aad4bb73a7e7379a649e4d8e50 (patch)
tree395640a0a5aeab7e0ebb807764923628f508dc54 /drivers/xen/balloon.c
parent81b286e0f1fe520f2a96f736ffa7e508ac9139ba (diff)
xen/balloon: use hotplugged pages for foreign mappings etc.
alloc_xenballooned_pages() is used to get ballooned pages to back foreign mappings etc. Instead of having to balloon out real pages, use (if supported) hotplugged memory. This makes more memory available to the guest and reduces fragmentation in the p2m. This is only enabled if the xen.balloon.hotplug_unpopulated sysctl is set to 1. This sysctl defaults to 0 in case the udev rules to automatically online hotplugged memory do not exist. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- v3: - Add xen.balloon.hotplug_unpopulated sysctl to enable use of hotplug for unpopulated pages.
Diffstat (limited to 'drivers/xen/balloon.c')
-rw-r--r--drivers/xen/balloon.c90
1 files changed, 80 insertions, 10 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 7ec933d505d2..25fd1bd949d8 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -55,6 +55,7 @@
55#include <linux/memory_hotplug.h> 55#include <linux/memory_hotplug.h>
56#include <linux/percpu-defs.h> 56#include <linux/percpu-defs.h>
57#include <linux/slab.h> 57#include <linux/slab.h>
58#include <linux/sysctl.h>
58 59
59#include <asm/page.h> 60#include <asm/page.h>
60#include <asm/pgalloc.h> 61#include <asm/pgalloc.h>
@@ -71,6 +72,46 @@
71#include <xen/features.h> 72#include <xen/features.h>
72#include <xen/page.h> 73#include <xen/page.h>
73 74
75static int xen_hotplug_unpopulated;
76
77#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
78
79static int zero;
80static int one = 1;
81
82static struct ctl_table balloon_table[] = {
83 {
84 .procname = "hotplug_unpopulated",
85 .data = &xen_hotplug_unpopulated,
86 .maxlen = sizeof(int),
87 .mode = 0644,
88 .proc_handler = proc_dointvec_minmax,
89 .extra1 = &zero,
90 .extra2 = &one,
91 },
92 { }
93};
94
95static struct ctl_table balloon_root[] = {
96 {
97 .procname = "balloon",
98 .mode = 0555,
99 .child = balloon_table,
100 },
101 { }
102};
103
104static struct ctl_table xen_root[] = {
105 {
106 .procname = "xen",
107 .mode = 0555,
108 .child = balloon_root,
109 },
110 { }
111};
112
113#endif
114
74/* 115/*
75 * balloon_process() state: 116 * balloon_process() state:
76 * 117 *
@@ -99,6 +140,7 @@ static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
99 140
100/* List of ballooned pages, threaded through the mem_map array. */ 141/* List of ballooned pages, threaded through the mem_map array. */
101static LIST_HEAD(ballooned_pages); 142static LIST_HEAD(ballooned_pages);
143static DECLARE_WAIT_QUEUE_HEAD(balloon_wq);
102 144
103/* Main work function, always executed in process context. */ 145/* Main work function, always executed in process context. */
104static void balloon_process(struct work_struct *work); 146static void balloon_process(struct work_struct *work);
@@ -127,6 +169,7 @@ static void __balloon_append(struct page *page)
127 list_add(&page->lru, &ballooned_pages); 169 list_add(&page->lru, &ballooned_pages);
128 balloon_stats.balloon_low++; 170 balloon_stats.balloon_low++;
129 } 171 }
172 wake_up(&balloon_wq);
130} 173}
131 174
132static void balloon_append(struct page *page) 175static void balloon_append(struct page *page)
@@ -242,7 +285,8 @@ static enum bp_state reserve_additional_memory(void)
242 int nid, rc; 285 int nid, rc;
243 unsigned long balloon_hotplug; 286 unsigned long balloon_hotplug;
244 287
245 credit = balloon_stats.target_pages - balloon_stats.total_pages; 288 credit = balloon_stats.target_pages + balloon_stats.target_unpopulated
289 - balloon_stats.total_pages;
246 290
247 /* 291 /*
248 * Already hotplugged enough pages? Wait for them to be 292 * Already hotplugged enough pages? Wait for them to be
@@ -323,7 +367,7 @@ static struct notifier_block xen_memory_nb = {
323static enum bp_state reserve_additional_memory(void) 367static enum bp_state reserve_additional_memory(void)
324{ 368{
325 balloon_stats.target_pages = balloon_stats.current_pages; 369 balloon_stats.target_pages = balloon_stats.current_pages;
326 return BP_DONE; 370 return BP_ECANCELED;
327} 371}
328#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */ 372#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
329 373
@@ -516,6 +560,28 @@ void balloon_set_new_target(unsigned long target)
516} 560}
517EXPORT_SYMBOL_GPL(balloon_set_new_target); 561EXPORT_SYMBOL_GPL(balloon_set_new_target);
518 562
563static int add_ballooned_pages(int nr_pages)
564{
565 enum bp_state st;
566
567 if (xen_hotplug_unpopulated) {
568 st = reserve_additional_memory();
569 if (st != BP_ECANCELED) {
570 mutex_unlock(&balloon_mutex);
571 wait_event(balloon_wq,
572 !list_empty(&ballooned_pages));
573 mutex_lock(&balloon_mutex);
574 return 0;
575 }
576 }
577
578 st = decrease_reservation(nr_pages, GFP_USER);
579 if (st != BP_DONE)
580 return -ENOMEM;
581
582 return 0;
583}
584
519/** 585/**
520 * alloc_xenballooned_pages - get pages that have been ballooned out 586 * alloc_xenballooned_pages - get pages that have been ballooned out
521 * @nr_pages: Number of pages to get 587 * @nr_pages: Number of pages to get
@@ -526,27 +592,28 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages)
526{ 592{
527 int pgno = 0; 593 int pgno = 0;
528 struct page *page; 594 struct page *page;
595 int ret;
596
529 mutex_lock(&balloon_mutex); 597 mutex_lock(&balloon_mutex);
598
599 balloon_stats.target_unpopulated += nr_pages;
600
530 while (pgno < nr_pages) { 601 while (pgno < nr_pages) {
531 page = balloon_retrieve(true); 602 page = balloon_retrieve(true);
532 if (page) { 603 if (page) {
533 pages[pgno++] = page; 604 pages[pgno++] = page;
534 } else { 605 } else {
535 enum bp_state st; 606 ret = add_ballooned_pages(nr_pages - pgno);
536 st = decrease_reservation(nr_pages - pgno, GFP_USER); 607 if (ret < 0)
537 if (st != BP_DONE)
538 goto out_undo; 608 goto out_undo;
539 } 609 }
540 } 610 }
541 mutex_unlock(&balloon_mutex); 611 mutex_unlock(&balloon_mutex);
542 return 0; 612 return 0;
543 out_undo: 613 out_undo:
544 while (pgno)
545 balloon_append(pages[--pgno]);
546 /* Free the memory back to the kernel soon */
547 schedule_delayed_work(&balloon_worker, 0);
548 mutex_unlock(&balloon_mutex); 614 mutex_unlock(&balloon_mutex);
549 return -ENOMEM; 615 free_xenballooned_pages(pgno, pages);
616 return ret;
550} 617}
551EXPORT_SYMBOL(alloc_xenballooned_pages); 618EXPORT_SYMBOL(alloc_xenballooned_pages);
552 619
@@ -566,6 +633,8 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
566 balloon_append(pages[i]); 633 balloon_append(pages[i]);
567 } 634 }
568 635
636 balloon_stats.target_unpopulated -= nr_pages;
637
569 /* The balloon may be too large now. Shrink it if needed. */ 638 /* The balloon may be too large now. Shrink it if needed. */
570 if (current_credit()) 639 if (current_credit())
571 schedule_delayed_work(&balloon_worker, 0); 640 schedule_delayed_work(&balloon_worker, 0);
@@ -623,6 +692,7 @@ static int __init balloon_init(void)
623#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG 692#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
624 set_online_page_callback(&xen_online_page); 693 set_online_page_callback(&xen_online_page);
625 register_memory_notifier(&xen_memory_nb); 694 register_memory_notifier(&xen_memory_nb);
695 register_sysctl_table(xen_root);
626#endif 696#endif
627 697
628 /* 698 /*