1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * mm/balloon_compaction.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Common interface for making balloon pages movable by compaction.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2012, Red Hat, Inc. Rafael Aquini <aquini@redhat.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #include <linux/mm.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/export.h>
12*4882a593Smuzhiyun #include <linux/balloon_compaction.h>
13*4882a593Smuzhiyun
balloon_page_enqueue_one(struct balloon_dev_info * b_dev_info,struct page * page)14*4882a593Smuzhiyun static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
15*4882a593Smuzhiyun struct page *page)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun * Block others from accessing the 'page' when we get around to
19*4882a593Smuzhiyun * establishing additional references. We should be the only one
20*4882a593Smuzhiyun * holding a reference to the 'page' at this point. If we are not, then
21*4882a593Smuzhiyun * memory corruption is possible and we should stop execution.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun BUG_ON(!trylock_page(page));
24*4882a593Smuzhiyun balloon_page_insert(b_dev_info, page);
25*4882a593Smuzhiyun unlock_page(page);
26*4882a593Smuzhiyun __count_vm_event(BALLOON_INFLATE);
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /**
30*4882a593Smuzhiyun * balloon_page_list_enqueue() - inserts a list of pages into the balloon page
31*4882a593Smuzhiyun * list.
32*4882a593Smuzhiyun * @b_dev_info: balloon device descriptor where we will insert a new page to
33*4882a593Smuzhiyun * @pages: pages to enqueue - allocated using balloon_page_alloc.
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * Driver must call this function to properly enqueue balloon pages before
36*4882a593Smuzhiyun * definitively removing them from the guest system.
37*4882a593Smuzhiyun *
38*4882a593Smuzhiyun * Return: number of pages that were enqueued.
39*4882a593Smuzhiyun */
balloon_page_list_enqueue(struct balloon_dev_info * b_dev_info,struct list_head * pages)40*4882a593Smuzhiyun size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
41*4882a593Smuzhiyun struct list_head *pages)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun struct page *page, *tmp;
44*4882a593Smuzhiyun unsigned long flags;
45*4882a593Smuzhiyun size_t n_pages = 0;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun spin_lock_irqsave(&b_dev_info->pages_lock, flags);
48*4882a593Smuzhiyun list_for_each_entry_safe(page, tmp, pages, lru) {
49*4882a593Smuzhiyun list_del(&page->lru);
50*4882a593Smuzhiyun balloon_page_enqueue_one(b_dev_info, page);
51*4882a593Smuzhiyun n_pages++;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
54*4882a593Smuzhiyun return n_pages;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(balloon_page_list_enqueue);
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /**
59*4882a593Smuzhiyun * balloon_page_list_dequeue() - removes pages from balloon's page list and
60*4882a593Smuzhiyun * returns a list of the pages.
61*4882a593Smuzhiyun * @b_dev_info: balloon device decriptor where we will grab a page from.
62*4882a593Smuzhiyun * @pages: pointer to the list of pages that would be returned to the caller.
63*4882a593Smuzhiyun * @n_req_pages: number of requested pages.
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * Driver must call this function to properly de-allocate a previous enlisted
66*4882a593Smuzhiyun * balloon pages before definitively releasing it back to the guest system.
67*4882a593Smuzhiyun * This function tries to remove @n_req_pages from the ballooned pages and
68*4882a593Smuzhiyun * return them to the caller in the @pages list.
69*4882a593Smuzhiyun *
70*4882a593Smuzhiyun * Note that this function may fail to dequeue some pages even if the balloon
71*4882a593Smuzhiyun * isn't empty - since the page list can be temporarily empty due to compaction
72*4882a593Smuzhiyun * of isolated pages.
73*4882a593Smuzhiyun *
74*4882a593Smuzhiyun * Return: number of pages that were added to the @pages list.
75*4882a593Smuzhiyun */
balloon_page_list_dequeue(struct balloon_dev_info * b_dev_info,struct list_head * pages,size_t n_req_pages)76*4882a593Smuzhiyun size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
77*4882a593Smuzhiyun struct list_head *pages, size_t n_req_pages)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct page *page, *tmp;
80*4882a593Smuzhiyun unsigned long flags;
81*4882a593Smuzhiyun size_t n_pages = 0;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun spin_lock_irqsave(&b_dev_info->pages_lock, flags);
84*4882a593Smuzhiyun list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
85*4882a593Smuzhiyun if (n_pages == n_req_pages)
86*4882a593Smuzhiyun break;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /*
89*4882a593Smuzhiyun * Block others from accessing the 'page' while we get around to
90*4882a593Smuzhiyun * establishing additional references and preparing the 'page'
91*4882a593Smuzhiyun * to be released by the balloon driver.
92*4882a593Smuzhiyun */
93*4882a593Smuzhiyun if (!trylock_page(page))
94*4882a593Smuzhiyun continue;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun if (IS_ENABLED(CONFIG_BALLOON_COMPACTION) &&
97*4882a593Smuzhiyun PageIsolated(page)) {
98*4882a593Smuzhiyun /* raced with isolation */
99*4882a593Smuzhiyun unlock_page(page);
100*4882a593Smuzhiyun continue;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun balloon_page_delete(page);
103*4882a593Smuzhiyun __count_vm_event(BALLOON_DEFLATE);
104*4882a593Smuzhiyun list_add(&page->lru, pages);
105*4882a593Smuzhiyun unlock_page(page);
106*4882a593Smuzhiyun n_pages++;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun return n_pages;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(balloon_page_list_dequeue);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun * balloon_page_alloc - allocates a new page for insertion into the balloon
116*4882a593Smuzhiyun * page list.
117*4882a593Smuzhiyun *
118*4882a593Smuzhiyun * Driver must call this function to properly allocate a new balloon page.
119*4882a593Smuzhiyun * Driver must call balloon_page_enqueue before definitively removing the page
120*4882a593Smuzhiyun * from the guest system.
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun * Return: struct page for the allocated page or NULL on allocation failure.
123*4882a593Smuzhiyun */
balloon_page_alloc(void)124*4882a593Smuzhiyun struct page *balloon_page_alloc(void)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun struct page *page = alloc_page(balloon_mapping_gfp_mask() |
127*4882a593Smuzhiyun __GFP_NOMEMALLOC | __GFP_NORETRY |
128*4882a593Smuzhiyun __GFP_NOWARN);
129*4882a593Smuzhiyun return page;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(balloon_page_alloc);
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun /*
134*4882a593Smuzhiyun * balloon_page_enqueue - inserts a new page into the balloon page list.
135*4882a593Smuzhiyun *
136*4882a593Smuzhiyun * @b_dev_info: balloon device descriptor where we will insert a new page
137*4882a593Smuzhiyun * @page: new page to enqueue - allocated using balloon_page_alloc.
138*4882a593Smuzhiyun *
139*4882a593Smuzhiyun * Drivers must call this function to properly enqueue a new allocated balloon
140*4882a593Smuzhiyun * page before definitively removing the page from the guest system.
141*4882a593Smuzhiyun *
142*4882a593Smuzhiyun * Drivers must not call balloon_page_enqueue on pages that have been pushed to
143*4882a593Smuzhiyun * a list with balloon_page_push before removing them with balloon_page_pop. To
144*4882a593Smuzhiyun * enqueue a list of pages, use balloon_page_list_enqueue instead.
145*4882a593Smuzhiyun */
balloon_page_enqueue(struct balloon_dev_info * b_dev_info,struct page * page)146*4882a593Smuzhiyun void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
147*4882a593Smuzhiyun struct page *page)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun unsigned long flags;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun spin_lock_irqsave(&b_dev_info->pages_lock, flags);
152*4882a593Smuzhiyun balloon_page_enqueue_one(b_dev_info, page);
153*4882a593Smuzhiyun spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(balloon_page_enqueue);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /*
158*4882a593Smuzhiyun * balloon_page_dequeue - removes a page from balloon's page list and returns
159*4882a593Smuzhiyun * its address to allow the driver to release the page.
160*4882a593Smuzhiyun * @b_dev_info: balloon device decriptor where we will grab a page from.
161*4882a593Smuzhiyun *
162*4882a593Smuzhiyun * Driver must call this function to properly dequeue a previously enqueued page
163*4882a593Smuzhiyun * before definitively releasing it back to the guest system.
164*4882a593Smuzhiyun *
165*4882a593Smuzhiyun * Caller must perform its own accounting to ensure that this
166*4882a593Smuzhiyun * function is called only if some pages are actually enqueued.
167*4882a593Smuzhiyun *
168*4882a593Smuzhiyun * Note that this function may fail to dequeue some pages even if there are
169*4882a593Smuzhiyun * some enqueued pages - since the page list can be temporarily empty due to
170*4882a593Smuzhiyun * the compaction of isolated pages.
171*4882a593Smuzhiyun *
172*4882a593Smuzhiyun * TODO: remove the caller accounting requirements, and allow caller to wait
173*4882a593Smuzhiyun * until all pages can be dequeued.
174*4882a593Smuzhiyun *
175*4882a593Smuzhiyun * Return: struct page for the dequeued page, or NULL if no page was dequeued.
176*4882a593Smuzhiyun */
balloon_page_dequeue(struct balloon_dev_info * b_dev_info)177*4882a593Smuzhiyun struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun unsigned long flags;
180*4882a593Smuzhiyun LIST_HEAD(pages);
181*4882a593Smuzhiyun int n_pages;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun n_pages = balloon_page_list_dequeue(b_dev_info, &pages, 1);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (n_pages != 1) {
186*4882a593Smuzhiyun /*
187*4882a593Smuzhiyun * If we are unable to dequeue a balloon page because the page
188*4882a593Smuzhiyun * list is empty and there are no isolated pages, then something
189*4882a593Smuzhiyun * went out of track and some balloon pages are lost.
190*4882a593Smuzhiyun * BUG() here, otherwise the balloon driver may get stuck in
191*4882a593Smuzhiyun * an infinite loop while attempting to release all its pages.
192*4882a593Smuzhiyun */
193*4882a593Smuzhiyun spin_lock_irqsave(&b_dev_info->pages_lock, flags);
194*4882a593Smuzhiyun if (unlikely(list_empty(&b_dev_info->pages) &&
195*4882a593Smuzhiyun !b_dev_info->isolated_pages))
196*4882a593Smuzhiyun BUG();
197*4882a593Smuzhiyun spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
198*4882a593Smuzhiyun return NULL;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun return list_first_entry(&pages, struct page, lru);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(balloon_page_dequeue);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun #ifdef CONFIG_BALLOON_COMPACTION
205*4882a593Smuzhiyun
balloon_page_isolate(struct page * page,isolate_mode_t mode)206*4882a593Smuzhiyun bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun struct balloon_dev_info *b_dev_info = balloon_page_device(page);
210*4882a593Smuzhiyun unsigned long flags;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun spin_lock_irqsave(&b_dev_info->pages_lock, flags);
213*4882a593Smuzhiyun list_del(&page->lru);
214*4882a593Smuzhiyun b_dev_info->isolated_pages++;
215*4882a593Smuzhiyun spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return true;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
balloon_page_putback(struct page * page)220*4882a593Smuzhiyun void balloon_page_putback(struct page *page)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct balloon_dev_info *b_dev_info = balloon_page_device(page);
223*4882a593Smuzhiyun unsigned long flags;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun spin_lock_irqsave(&b_dev_info->pages_lock, flags);
226*4882a593Smuzhiyun list_add(&page->lru, &b_dev_info->pages);
227*4882a593Smuzhiyun b_dev_info->isolated_pages--;
228*4882a593Smuzhiyun spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /* move_to_new_page() counterpart for a ballooned page */
balloon_page_migrate(struct address_space * mapping,struct page * newpage,struct page * page,enum migrate_mode mode)233*4882a593Smuzhiyun int balloon_page_migrate(struct address_space *mapping,
234*4882a593Smuzhiyun struct page *newpage, struct page *page,
235*4882a593Smuzhiyun enum migrate_mode mode)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun struct balloon_dev_info *balloon = balloon_page_device(page);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /*
240*4882a593Smuzhiyun * We can not easily support the no copy case here so ignore it as it
241*4882a593Smuzhiyun * is unlikely to be used with balloon pages. See include/linux/hmm.h
242*4882a593Smuzhiyun * for a user of the MIGRATE_SYNC_NO_COPY mode.
243*4882a593Smuzhiyun */
244*4882a593Smuzhiyun if (mode == MIGRATE_SYNC_NO_COPY)
245*4882a593Smuzhiyun return -EINVAL;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun VM_BUG_ON_PAGE(!PageLocked(page), page);
248*4882a593Smuzhiyun VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun return balloon->migratepage(balloon, newpage, page, mode);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun const struct address_space_operations balloon_aops = {
254*4882a593Smuzhiyun .migratepage = balloon_page_migrate,
255*4882a593Smuzhiyun .isolate_page = balloon_page_isolate,
256*4882a593Smuzhiyun .putback_page = balloon_page_putback,
257*4882a593Smuzhiyun };
258*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(balloon_aops);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun #endif /* CONFIG_BALLOON_COMPACTION */
261