Skip to content

Commit 418a3ab

Browse files
anadavgregkh
authored andcommitted
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 <[email protected]> Cc: [email protected] Cc: [email protected] Acked-by: Michael S. Tsirkin <[email protected]> Reviewed-by: Xavier Deguillard <[email protected]> Signed-off-by: Nadav Amit <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 687685a commit 418a3ab

File tree

2 files changed

+110
-38
lines changed

2 files changed

+110
-38
lines changed

include/linux/balloon_compaction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ extern struct page *balloon_page_alloc(void);
6464
extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
6565
struct page *page);
6666
extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
67+
extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
68+
struct list_head *pages);
69+
extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
70+
struct list_head *pages, size_t n_req_pages);
6771

6872
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
6973
{

mm/balloon_compaction.c

Lines changed: 106 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,105 @@
1010
#include <linux/export.h>
1111
#include <linux/balloon_compaction.h>
1212

13+
static 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+
*/
40+
size_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+
}
55+
EXPORT_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+
*/
74+
size_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+
}
110+
EXPORT_SYMBOL_GPL(balloon_page_list_dequeue);
111+
13112
/*
14113
* balloon_page_alloc - allocates a new page for insertion into the balloon
15114
* page list.
@@ -43,17 +142,9 @@ void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
43142
{
44143
unsigned long flags;
45144

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));
52145
spin_lock_irqsave(&b_dev_info->pages_lock, flags);
53-
balloon_page_insert(b_dev_info, page);
54-
__count_vm_event(BALLOON_INFLATE);
146+
balloon_page_enqueue_one(b_dev_info, page);
55147
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
56-
unlock_page(page);
57148
}
58149
EXPORT_SYMBOL_GPL(balloon_page_enqueue);
59150

@@ -70,36 +161,13 @@ EXPORT_SYMBOL_GPL(balloon_page_enqueue);
70161
*/
71162
struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
72163
{
73-
struct page *page, *tmp;
74164
unsigned long flags;
75-
bool dequeued_page;
165+
LIST_HEAD(pages);
166+
int n_pages;
76167

77-
dequeued_page = false;
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);
168+
n_pages = balloon_page_list_dequeue(b_dev_info, &pages, 1);
101169

102-
if (!dequeued_page) {
170+
if (n_pages != 1) {
103171
/*
104172
* If we are unable to dequeue a balloon page because the page
105173
* 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)
112180
!b_dev_info->isolated_pages))
113181
BUG();
114182
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
115-
page = NULL;
183+
return NULL;
116184
}
117-
return page;
185+
return list_first_entry(&pages, struct page, lru);
118186
}
119187
EXPORT_SYMBOL_GPL(balloon_page_dequeue);
120188

0 commit comments

Comments
 (0)