/* 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 */ #ifndef _LINUX_BALLOON_H #define _LINUX_BALLOON_H #include #include #include #include #include #include /* * 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 */