Skip to content

Commit b1123ea

Browse files
minchanktorvalds
authored andcommitted
mm: balloon: use general non-lru movable page feature
Now, VM has a feature to migrate non-lru movable pages so balloon doesn't need custom migration hooks in migrate.c and compaction.c. Instead, this patch implements the page->mapping->a_ops-> {isolate|migrate|putback} functions. With that, we could remove hooks for ballooning in general migration functions and make balloon compaction simple. [akpm@linux-foundation.org: compaction.h requires that the includer first include node.h] Link: http://lkml.kernel.org/r/1464736881-24886-4-git-send-email-minchan@kernel.org Signed-off-by: Gioh Kim <gi-oh.kim@profitbricks.com> Signed-off-by: Minchan Kim <minchan@kernel.org> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Rafael Aquini <aquini@redhat.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent bda807d commit b1123ea

File tree

7 files changed

+86
-145
lines changed

7 files changed

+86
-145
lines changed

drivers/virtio/virtio_balloon.c

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/oom.h>
3131
#include <linux/wait.h>
3232
#include <linux/mm.h>
33+
#include <linux/mount.h>
3334

3435
/*
3536
* Balloon device works in 4K page units. So each page is pointed to by
@@ -45,6 +46,10 @@ static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
4546
module_param(oom_pages, int, S_IRUSR | S_IWUSR);
4647
MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
4748

49+
#ifdef CONFIG_BALLOON_COMPACTION
50+
static struct vfsmount *balloon_mnt;
51+
#endif
52+
4853
struct virtio_balloon {
4954
struct virtio_device *vdev;
5055
struct virtqueue *inflate_vq, *deflate_vq, *stats_vq;
@@ -488,8 +493,26 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
488493

489494
put_page(page); /* balloon reference */
490495

491-
return MIGRATEPAGE_SUCCESS;
496+
return 0;
492497
}
498+
499+
static struct dentry *balloon_mount(struct file_system_type *fs_type,
500+
int flags, const char *dev_name, void *data)
501+
{
502+
static const struct dentry_operations ops = {
503+
.d_dname = simple_dname,
504+
};
505+
506+
return mount_pseudo(fs_type, "balloon-kvm:", NULL, &ops,
507+
BALLOON_KVM_MAGIC);
508+
}
509+
510+
static struct file_system_type balloon_fs = {
511+
.name = "balloon-kvm",
512+
.mount = balloon_mount,
513+
.kill_sb = kill_anon_super,
514+
};
515+
493516
#endif /* CONFIG_BALLOON_COMPACTION */
494517

495518
static int virtballoon_probe(struct virtio_device *vdev)
@@ -519,9 +542,6 @@ static int virtballoon_probe(struct virtio_device *vdev)
519542
vb->vdev = vdev;
520543

521544
balloon_devinfo_init(&vb->vb_dev_info);
522-
#ifdef CONFIG_BALLOON_COMPACTION
523-
vb->vb_dev_info.migratepage = virtballoon_migratepage;
524-
#endif
525545

526546
err = init_vqs(vb);
527547
if (err)
@@ -531,13 +551,33 @@ static int virtballoon_probe(struct virtio_device *vdev)
531551
vb->nb.priority = VIRTBALLOON_OOM_NOTIFY_PRIORITY;
532552
err = register_oom_notifier(&vb->nb);
533553
if (err < 0)
534-
goto out_oom_notify;
554+
goto out_del_vqs;
555+
556+
#ifdef CONFIG_BALLOON_COMPACTION
557+
balloon_mnt = kern_mount(&balloon_fs);
558+
if (IS_ERR(balloon_mnt)) {
559+
err = PTR_ERR(balloon_mnt);
560+
unregister_oom_notifier(&vb->nb);
561+
goto out_del_vqs;
562+
}
563+
564+
vb->vb_dev_info.migratepage = virtballoon_migratepage;
565+
vb->vb_dev_info.inode = alloc_anon_inode(balloon_mnt->mnt_sb);
566+
if (IS_ERR(vb->vb_dev_info.inode)) {
567+
err = PTR_ERR(vb->vb_dev_info.inode);
568+
kern_unmount(balloon_mnt);
569+
unregister_oom_notifier(&vb->nb);
570+
vb->vb_dev_info.inode = NULL;
571+
goto out_del_vqs;
572+
}
573+
vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops;
574+
#endif
535575

536576
virtio_device_ready(vdev);
537577

538578
return 0;
539579

540-
out_oom_notify:
580+
out_del_vqs:
541581
vdev->config->del_vqs(vdev);
542582
out_free_vb:
543583
kfree(vb);
@@ -571,6 +611,8 @@ static void virtballoon_remove(struct virtio_device *vdev)
571611
cancel_work_sync(&vb->update_balloon_stats_work);
572612

573613
remove_common(vb);
614+
if (vb->vb_dev_info.inode)
615+
iput(vb->vb_dev_info.inode);
574616
kfree(vb);
575617
}
576618

include/linux/balloon_compaction.h

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@
4545
#define _LINUX_BALLOON_COMPACTION_H
4646
#include <linux/pagemap.h>
4747
#include <linux/page-flags.h>
48-
#include <linux/migrate.h>
48+
#include <linux/node.h>
49+
#include <linux/compaction.h>
4950
#include <linux/gfp.h>
5051
#include <linux/err.h>
52+
#include <linux/fs.h>
5153

5254
/*
5355
* Balloon device information descriptor.
@@ -62,6 +64,7 @@ struct balloon_dev_info {
6264
struct list_head pages; /* Pages enqueued & handled to Host */
6365
int (*migratepage)(struct balloon_dev_info *, struct page *newpage,
6466
struct page *page, enum migrate_mode mode);
67+
struct inode *inode;
6568
};
6669

6770
extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info);
@@ -73,44 +76,18 @@ static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
7376
spin_lock_init(&balloon->pages_lock);
7477
INIT_LIST_HEAD(&balloon->pages);
7578
balloon->migratepage = NULL;
79+
balloon->inode = NULL;
7680
}
7781

7882
#ifdef CONFIG_BALLOON_COMPACTION
79-
extern bool balloon_page_isolate(struct page *page);
83+
extern const struct address_space_operations balloon_aops;
84+
extern bool balloon_page_isolate(struct page *page,
85+
isolate_mode_t mode);
8086
extern void balloon_page_putback(struct page *page);
81-
extern int balloon_page_migrate(struct page *newpage,
87+
extern int balloon_page_migrate(struct address_space *mapping,
88+
struct page *newpage,
8289
struct page *page, enum migrate_mode mode);
8390

84-
/*
85-
* __is_movable_balloon_page - helper to perform @page PageBalloon tests
86-
*/
87-
static inline bool __is_movable_balloon_page(struct page *page)
88-
{
89-
return PageBalloon(page);
90-
}
91-
92-
/*
93-
* balloon_page_movable - test PageBalloon to identify balloon pages
94-
* and PagePrivate to check that the page is not
95-
* isolated and can be moved by compaction/migration.
96-
*
97-
* As we might return false positives in the case of a balloon page being just
98-
* released under us, this need to be re-tested later, under the page lock.
99-
*/
100-
static inline bool balloon_page_movable(struct page *page)
101-
{
102-
return PageBalloon(page) && PagePrivate(page);
103-
}
104-
105-
/*
106-
* isolated_balloon_page - identify an isolated balloon page on private
107-
* compaction/migration page lists.
108-
*/
109-
static inline bool isolated_balloon_page(struct page *page)
110-
{
111-
return PageBalloon(page);
112-
}
113-
11491
/*
11592
* balloon_page_insert - insert a page into the balloon's page list and make
11693
* the page->private assignment accordingly.
@@ -124,7 +101,7 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
124101
struct page *page)
125102
{
126103
__SetPageBalloon(page);
127-
SetPagePrivate(page);
104+
__SetPageMovable(page, balloon->inode->i_mapping);
128105
set_page_private(page, (unsigned long)balloon);
129106
list_add(&page->lru, &balloon->pages);
130107
}
@@ -140,11 +117,14 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
140117
static inline void balloon_page_delete(struct page *page)
141118
{
142119
__ClearPageBalloon(page);
120+
__ClearPageMovable(page);
143121
set_page_private(page, 0);
144-
if (PagePrivate(page)) {
145-
ClearPagePrivate(page);
122+
/*
123+
* No touch page.lru field once @page has been isolated
124+
* because VM is using the field.
125+
*/
126+
if (!PageIsolated(page))
146127
list_del(&page->lru);
147-
}
148128
}
149129

150130
/*

include/uapi/linux/magic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,6 @@
8080
#define BPF_FS_MAGIC 0xcafe4a11
8181
/* Since UDF 2.01 is ISO 13346 based... */
8282
#define UDF_SUPER_MAGIC 0x15013346
83+
#define BALLOON_KVM_MAGIC 0x13661366
8384

8485
#endif /* __LINUX_MAGIC_H__ */

mm/balloon_compaction.c

Lines changed: 17 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info)
7070
*/
7171
if (trylock_page(page)) {
7272
#ifdef CONFIG_BALLOON_COMPACTION
73-
if (!PagePrivate(page)) {
73+
if (PageIsolated(page)) {
7474
/* raced with isolation */
7575
unlock_page(page);
7676
continue;
@@ -106,110 +106,50 @@ EXPORT_SYMBOL_GPL(balloon_page_dequeue);
106106

107107
#ifdef CONFIG_BALLOON_COMPACTION
108108

109-
static inline void __isolate_balloon_page(struct page *page)
109+
bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
110+
110111
{
111112
struct balloon_dev_info *b_dev_info = balloon_page_device(page);
112113
unsigned long flags;
113114

114115
spin_lock_irqsave(&b_dev_info->pages_lock, flags);
115-
ClearPagePrivate(page);
116116
list_del(&page->lru);
117117
b_dev_info->isolated_pages++;
118118
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
119+
120+
return true;
119121
}
120122

121-
static inline void __putback_balloon_page(struct page *page)
123+
void balloon_page_putback(struct page *page)
122124
{
123125
struct balloon_dev_info *b_dev_info = balloon_page_device(page);
124126
unsigned long flags;
125127

126128
spin_lock_irqsave(&b_dev_info->pages_lock, flags);
127-
SetPagePrivate(page);
128129
list_add(&page->lru, &b_dev_info->pages);
129130
b_dev_info->isolated_pages--;
130131
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
131132
}
132133

133-
/* __isolate_lru_page() counterpart for a ballooned page */
134-
bool balloon_page_isolate(struct page *page)
135-
{
136-
/*
137-
* Avoid burning cycles with pages that are yet under __free_pages(),
138-
* or just got freed under us.
139-
*
140-
* In case we 'win' a race for a balloon page being freed under us and
141-
* raise its refcount preventing __free_pages() from doing its job
142-
* the put_page() at the end of this block will take care of
143-
* release this page, thus avoiding a nasty leakage.
144-
*/
145-
if (likely(get_page_unless_zero(page))) {
146-
/*
147-
* As balloon pages are not isolated from LRU lists, concurrent
148-
* compaction threads can race against page migration functions
149-
* as well as race against the balloon driver releasing a page.
150-
*
151-
* In order to avoid having an already isolated balloon page
152-
* being (wrongly) re-isolated while it is under migration,
153-
* or to avoid attempting to isolate pages being released by
154-
* the balloon driver, lets be sure we have the page lock
155-
* before proceeding with the balloon page isolation steps.
156-
*/
157-
if (likely(trylock_page(page))) {
158-
/*
159-
* A ballooned page, by default, has PagePrivate set.
160-
* Prevent concurrent compaction threads from isolating
161-
* an already isolated balloon page by clearing it.
162-
*/
163-
if (balloon_page_movable(page)) {
164-
__isolate_balloon_page(page);
165-
unlock_page(page);
166-
return true;
167-
}
168-
unlock_page(page);
169-
}
170-
put_page(page);
171-
}
172-
return false;
173-
}
174-
175-
/* putback_lru_page() counterpart for a ballooned page */
176-
void balloon_page_putback(struct page *page)
177-
{
178-
/*
179-
* 'lock_page()' stabilizes the page and prevents races against
180-
* concurrent isolation threads attempting to re-isolate it.
181-
*/
182-
lock_page(page);
183-
184-
if (__is_movable_balloon_page(page)) {
185-
__putback_balloon_page(page);
186-
/* drop the extra ref count taken for page isolation */
187-
put_page(page);
188-
} else {
189-
WARN_ON(1);
190-
dump_page(page, "not movable balloon page");
191-
}
192-
unlock_page(page);
193-
}
194134

195135
/* move_to_new_page() counterpart for a ballooned page */
196-
int balloon_page_migrate(struct page *newpage,
197-
struct page *page, enum migrate_mode mode)
136+
int balloon_page_migrate(struct address_space *mapping,
137+
struct page *newpage, struct page *page,
138+
enum migrate_mode mode)
198139
{
199140
struct balloon_dev_info *balloon = balloon_page_device(page);
200-
int rc = -EAGAIN;
201141

202142
VM_BUG_ON_PAGE(!PageLocked(page), page);
203143
VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
204144

205-
if (WARN_ON(!__is_movable_balloon_page(page))) {
206-
dump_page(page, "not movable balloon page");
207-
return rc;
208-
}
145+
return balloon->migratepage(balloon, newpage, page, mode);
146+
}
209147

210-
if (balloon && balloon->migratepage)
211-
rc = balloon->migratepage(balloon, newpage, page, mode);
148+
const struct address_space_operations balloon_aops = {
149+
.migratepage = balloon_page_migrate,
150+
.isolate_page = balloon_page_isolate,
151+
.putback_page = balloon_page_putback,
152+
};
153+
EXPORT_SYMBOL_GPL(balloon_aops);
212154

213-
return rc;
214-
}
215155
#endif /* CONFIG_BALLOON_COMPACTION */

mm/compaction.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -791,13 +791,6 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
791791
* Skip any other type of page
792792
*/
793793
if (!PageLRU(page)) {
794-
if (unlikely(balloon_page_movable(page))) {
795-
if (balloon_page_isolate(page)) {
796-
/* Successfully isolated */
797-
goto isolate_success;
798-
}
799-
}
800-
801794
/*
802795
* __PageMovable can return false positive so we need
803796
* to verify it under page_lock.

0 commit comments

Comments
 (0)