| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Common interface for implementing a memory balloon, including support |
| * for migration of pages inflated in a memory balloon. |
| * |
| * Balloon page migration makes use of the general "movable_ops page migration" |
| * feature. |
| * |
| * page->private is used to reference the responsible balloon device. |
| * That these pages have movable_ops, and which movable_ops apply, |
| * is derived from the page type (PageOffline()) combined with the |
| * PG_movable_ops flag (PageMovableOps()). |
| * |
| * Once the page type and the PG_movable_ops are set, migration code |
| * can initiate page isolation by invoking the |
| * movable_operations()->isolate_page() callback |
| * |
| * As long as page->private is set, the page is either on the balloon list |
| * or isolated for migration. If page->private is not set, the page is |
| * either still getting inflated, or was deflated to be freed by the balloon |
| * driver soon. Isolation is impossible in both cases. |
| * |
| * As the page isolation scanning step a compaction thread does is a lockless |
| * procedure (from a page standpoint), it might bring some racy situations while |
| * performing balloon page migration. In order to sort out these racy scenarios |
| * and safely perform balloon's page migration we must, always, ensure following |
| * these simple rules: |
| * |
| * i. Inflation/deflation must set/clear page->private under the |
| * balloon_pages_lock |
| * |
| * ii. isolation or dequeueing procedure must remove the page from balloon |
| * device page list under balloon_pages_lock |
| * |
| * Copyright (C) 2012, Red Hat, Inc. Rafael Aquini <aquini@redhat.com> |
| */ |
| #ifndef _LINUX_BALLOON_H |
| #define _LINUX_BALLOON_H |
| #include <linux/pagemap.h> |
| #include <linux/page-flags.h> |
| #include <linux/migrate.h> |
| #include <linux/gfp.h> |
| #include <linux/err.h> |
| #include <linux/list.h> |
| |
| /* |
| * Balloon device information descriptor. |
| * This struct is used to allow the common balloon page migration interface |
| * procedures to find the proper balloon device holding memory pages they'll |
| * have to cope for page migration, as well as it serves the balloon driver as |
| * a page book-keeper for its registered balloon devices. |
| */ |
| struct balloon_dev_info { |
| unsigned long isolated_pages; /* # of isolated pages for migration */ |
| struct list_head pages; /* Pages enqueued & handled to Host */ |
| int (*migratepage)(struct balloon_dev_info *, struct page *newpage, |
| struct page *page, enum migrate_mode mode); |
| bool adjust_managed_page_count; |
| }; |
| |
| struct page *balloon_page_alloc(void); |
| void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, |
| struct page *page); |
| struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); |
| size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info, |
| struct list_head *pages); |
| size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info, |
| struct list_head *pages, size_t n_req_pages); |
| |
| static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) |
| { |
| balloon->isolated_pages = 0; |
| INIT_LIST_HEAD(&balloon->pages); |
| balloon->migratepage = NULL; |
| balloon->adjust_managed_page_count = false; |
| } |
| #endif /* _LINUX_BALLOON_H */ |