summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadav Amit <namit@vmware.com>2019-04-25 07:54:42 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-05-24 14:19:17 -0400
commit418a3ab1e7785799193c0f8628cd0f01c00a03ae (patch)
treed861dba41aab6ec9d35e6fc798cfe8cdaed5fcfb
parent687685a3f246756a2a8c0d45820be42066ffce05 (diff)
mm/balloon_compaction: List interfaces
Introduce interfaces for ballooning enqueueing and dequeueing of a list of pages. These interfaces reduce the overhead of storing and restoring IRQs by batching the operations. In addition they do not panic if the list of pages is empty. Cc: Jason Wang <jasowang@redhat.com> Cc: linux-mm@kvack.org Cc: virtualization@lists.linux-foundation.org Acked-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Xavier Deguillard <xdeguillard@vmware.com> Signed-off-by: Nadav Amit <namit@vmware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/balloon_compaction.h4
-rw-r--r--mm/balloon_compaction.c144
2 files changed, 110 insertions, 38 deletions
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index f31521dcb09a..338aa27e4773 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -64,6 +64,10 @@ extern struct page *balloon_page_alloc(void);
64extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, 64extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
65 struct page *page); 65 struct page *page);
66extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); 66extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
67extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
68 struct list_head *pages);
69extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
70 struct list_head *pages, size_t n_req_pages);
67 71
68static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) 72static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
69{ 73{
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index ef858d547e2d..b7bd72612c5a 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -10,6 +10,105 @@
10#include <linux/export.h> 10#include <linux/export.h>
11#include <linux/balloon_compaction.h> 11#include <linux/balloon_compaction.h>
12 12
13static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
14 struct page *page)
15{
16 /*
17 * Block others from accessing the 'page' when we get around to
18 * establishing additional references. We should be the only one
19 * holding a reference to the 'page' at this point. If we are not, then
20 * memory corruption is possible and we should stop execution.
21 */
22 BUG_ON(!trylock_page(page));
23 list_del(&page->lru);
24 balloon_page_insert(b_dev_info, page);
25 unlock_page(page);
26 __count_vm_event(BALLOON_INFLATE);
27}
28
29/**
30 * balloon_page_list_enqueue() - inserts a list of pages into the balloon page
31 * list.
32 * @b_dev_info: balloon device descriptor where we will insert a new page to
33 * @pages: pages to enqueue - allocated using balloon_page_alloc.
34 *
35 * Driver must call it to properly enqueue a balloon pages before definitively
36 * removing it from the guest system.
37 *
38 * Return: number of pages that were enqueued.
39 */
40size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
41 struct list_head *pages)
42{
43 struct page *page, *tmp;
44 unsigned long flags;
45 size_t n_pages = 0;
46
47 spin_lock_irqsave(&b_dev_info->pages_lock, flags);
48 list_for_each_entry_safe(page, tmp, pages, lru) {
49 balloon_page_enqueue_one(b_dev_info, page);
50 n_pages++;
51 }
52 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
53 return n_pages;
54}
55EXPORT_SYMBOL_GPL(balloon_page_list_enqueue);
56
57/**
58 * balloon_page_list_dequeue() - removes pages from balloon's page list and
59 * returns a list of the pages.
60 * @b_dev_info: balloon device decriptor where we will grab a page from.
61 * @pages: pointer to the list of pages that would be returned to the caller.
62 * @n_req_pages: number of requested pages.
63 *
64 * Driver must call this function to properly de-allocate a previous enlisted
65 * balloon pages before definetively releasing it back to the guest system.
66 * This function tries to remove @n_req_pages from the ballooned pages and
67 * return them to the caller in the @pages list.
68 *
69 * Note that this function may fail to dequeue some pages temporarily empty due
70 * to compaction isolated pages.
71 *
72 * Return: number of pages that were added to the @pages list.
73 */
74size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
75 struct list_head *pages, size_t n_req_pages)
76{
77 struct page *page, *tmp;
78 unsigned long flags;
79 size_t n_pages = 0;
80
81 spin_lock_irqsave(&b_dev_info->pages_lock, flags);
82 list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
83 if (n_pages == n_req_pages)
84 break;
85
86 /*
87 * Block others from accessing the 'page' while we get around to
88 * establishing additional references and preparing the 'page'
89 * to be released by the balloon driver.
90 */
91 if (!trylock_page(page))
92 continue;
93
94 if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) &&
95 PageIsolated(page)) {
96 /* raced with isolation */
97 unlock_page(page);
98 continue;
99 }
100 balloon_page_delete(page);
101 __count_vm_event(BALLOON_DEFLATE);
102 list_add(&page->lru, pages);
103 unlock_page(page);
104 n_pages++;
105 }
106 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
107
108 return n_pages;
109}
110EXPORT_SYMBOL_GPL(balloon_page_list_dequeue);
111
13/* 112/*
14 * balloon_page_alloc - allocates a new page for insertion into the balloon 113 * balloon_page_alloc - allocates a new page for insertion into the balloon
15 * page list. 114 * page list.
@@ -43,17 +142,9 @@ void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
43{ 142{
44 unsigned long flags; 143 unsigned long flags;
45 144
46 /*
47 * Block others from accessing the 'page' when we get around to
48 * establishing additional references. We should be the only one
49 * holding a reference to the 'page' at this point.
50 */
51 BUG_ON(!trylock_page(page));
52 spin_lock_irqsave(&b_dev_info->pages_lock, flags); 145 spin_lock_irqsave(&b_dev_info->pages_lock, flags);
53 balloon_page_insert(b_dev_info, page); 146 balloon_page_enqueue_one(b_dev_info, page);
54 __count_vm_event(BALLOON_INFLATE);
55 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 147 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
56 unlock_page(page);
57} 148}
58EXPORT_SYMBOL_GPL(balloon_page_enqueue); 149EXPORT_SYMBOL_GPL(balloon_page_enqueue);
59 150
@@ -70,36 +161,13 @@ EXPORT_SYMBOL_GPL(balloon_page_enqueue);
70 */ 161 */
71struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info) 162struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
72{ 163{
73 struct page *page, *tmp;
74 unsigned long flags; 164 unsigned long flags;
75 bool dequeued_page; 165 LIST_HEAD(pages);
166 int n_pages;
76 167
77 dequeued_page = false; 168 n_pages = balloon_page_list_dequeue(b_dev_info, &pages, 1);
78 spin_lock_irqsave(&b_dev_info->pages_lock, flags);
79 list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
80 /*
81 * Block others from accessing the 'page' while we get around
82 * establishing additional references and preparing the 'page'
83 * to be released by the balloon driver.
84 */
85 if (trylock_page(page)) {
86#ifdef CONFIG_BALLOON_COMPACTION
87 if (PageIsolated(page)) {
88 /* raced with isolation */
89 unlock_page(page);
90 continue;
91 }
92#endif
93 balloon_page_delete(page);
94 __count_vm_event(BALLOON_DEFLATE);
95 unlock_page(page);
96 dequeued_page = true;
97 break;
98 }
99 }
100 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
101 169
102 if (!dequeued_page) { 170 if (n_pages != 1) {
103 /* 171 /*
104 * If we are unable to dequeue a balloon page because the page 172 * If we are unable to dequeue a balloon page because the page
105 * list is empty and there is no isolated pages, then something 173 * list is empty and there is no isolated pages, then something
@@ -112,9 +180,9 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
112 !b_dev_info->isolated_pages)) 180 !b_dev_info->isolated_pages))
113 BUG(); 181 BUG();
114 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags); 182 spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
115 page = NULL; 183 return NULL;
116 } 184 }
117 return page; 185 return list_first_entry(&pages, struct page, lru);
118} 186}
119EXPORT_SYMBOL_GPL(balloon_page_dequeue); 187EXPORT_SYMBOL_GPL(balloon_page_dequeue);
120 188