Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * include/linux/balloon_compaction.h
0004  *
0005  * Common interface definitions for making balloon pages movable by compaction.
0006  *
0007  * Balloon page migration makes use of the general non-lru movable page
0008  * feature.
0009  *
0010  * page->private is used to reference the responsible balloon device.
0011  * page->mapping is used in context of non-lru page migration to reference
0012  * the address space operations for page isolation/migration/compaction.
0013  *
0014  * As the page isolation scanning step a compaction thread does is a lockless
0015  * procedure (from a page standpoint), it might bring some racy situations while
0016  * performing balloon page compaction. In order to sort out these racy scenarios
0017  * and safely perform balloon's page compaction and migration we must, always,
0018  * ensure following these simple rules:
0019  *
0020  *   i. when updating a balloon's page ->mapping element, strictly do it under
0021  *      the following lock order, independently of the far superior
0022  *      locking scheme (lru_lock, balloon_lock):
0023  *      +-page_lock(page);
0024  *        +--spin_lock_irq(&b_dev_info->pages_lock);
0025  *              ... page->mapping updates here ...
0026  *
0027  *  ii. isolation or dequeueing procedure must remove the page from balloon
0028  *      device page list under b_dev_info->pages_lock.
0029  *
0030  * The functions provided by this interface are placed to help on coping with
0031  * the aforementioned balloon page corner case, as well as to ensure the simple
0032  * set of exposed rules are satisfied while we are dealing with balloon pages
0033  * compaction / migration.
0034  *
0035  * Copyright (C) 2012, Red Hat, Inc.  Rafael Aquini <aquini@redhat.com>
0036  */
0037 #ifndef _LINUX_BALLOON_COMPACTION_H
0038 #define _LINUX_BALLOON_COMPACTION_H
0039 #include <linux/pagemap.h>
0040 #include <linux/page-flags.h>
0041 #include <linux/migrate.h>
0042 #include <linux/gfp.h>
0043 #include <linux/err.h>
0044 #include <linux/fs.h>
0045 #include <linux/list.h>
0046 
0047 /*
0048  * Balloon device information descriptor.
0049  * This struct is used to allow the common balloon compaction interface
0050  * procedures to find the proper balloon device holding memory pages they'll
0051  * have to cope for page compaction / migration, as well as it serves the
0052  * balloon driver as a page book-keeper for its registered balloon devices.
0053  */
0054 struct balloon_dev_info {
0055     unsigned long isolated_pages;   /* # of isolated pages for migration */
0056     spinlock_t pages_lock;      /* Protection to pages list */
0057     struct list_head pages;     /* Pages enqueued & handled to Host */
0058     int (*migratepage)(struct balloon_dev_info *, struct page *newpage,
0059             struct page *page, enum migrate_mode mode);
0060 };
0061 
0062 extern struct page *balloon_page_alloc(void);
0063 extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
0064                  struct page *page);
0065 extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
0066 extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
0067                       struct list_head *pages);
0068 extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
0069                      struct list_head *pages, size_t n_req_pages);
0070 
0071 static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
0072 {
0073     balloon->isolated_pages = 0;
0074     spin_lock_init(&balloon->pages_lock);
0075     INIT_LIST_HEAD(&balloon->pages);
0076     balloon->migratepage = NULL;
0077 }
0078 
0079 #ifdef CONFIG_BALLOON_COMPACTION
0080 extern const struct movable_operations balloon_mops;
0081 
0082 /*
0083  * balloon_page_insert - insert a page into the balloon's page list and make
0084  *           the page->private assignment accordingly.
0085  * @balloon : pointer to balloon device
0086  * @page    : page to be assigned as a 'balloon page'
0087  *
0088  * Caller must ensure the page is locked and the spin_lock protecting balloon
0089  * pages list is held before inserting a page into the balloon device.
0090  */
0091 static inline void balloon_page_insert(struct balloon_dev_info *balloon,
0092                        struct page *page)
0093 {
0094     __SetPageOffline(page);
0095     __SetPageMovable(page, &balloon_mops);
0096     set_page_private(page, (unsigned long)balloon);
0097     list_add(&page->lru, &balloon->pages);
0098 }
0099 
0100 /*
0101  * balloon_page_delete - delete a page from balloon's page list and clear
0102  *           the page->private assignement accordingly.
0103  * @page    : page to be released from balloon's page list
0104  *
0105  * Caller must ensure the page is locked and the spin_lock protecting balloon
0106  * pages list is held before deleting a page from the balloon device.
0107  */
0108 static inline void balloon_page_delete(struct page *page)
0109 {
0110     __ClearPageOffline(page);
0111     __ClearPageMovable(page);
0112     set_page_private(page, 0);
0113     /*
0114      * No touch page.lru field once @page has been isolated
0115      * because VM is using the field.
0116      */
0117     if (!PageIsolated(page))
0118         list_del(&page->lru);
0119 }
0120 
0121 /*
0122  * balloon_page_device - get the b_dev_info descriptor for the balloon device
0123  *           that enqueues the given page.
0124  */
0125 static inline struct balloon_dev_info *balloon_page_device(struct page *page)
0126 {
0127     return (struct balloon_dev_info *)page_private(page);
0128 }
0129 
0130 static inline gfp_t balloon_mapping_gfp_mask(void)
0131 {
0132     return GFP_HIGHUSER_MOVABLE;
0133 }
0134 
0135 #else /* !CONFIG_BALLOON_COMPACTION */
0136 
0137 static inline void balloon_page_insert(struct balloon_dev_info *balloon,
0138                        struct page *page)
0139 {
0140     __SetPageOffline(page);
0141     list_add(&page->lru, &balloon->pages);
0142 }
0143 
0144 static inline void balloon_page_delete(struct page *page)
0145 {
0146     __ClearPageOffline(page);
0147     list_del(&page->lru);
0148 }
0149 
0150 static inline gfp_t balloon_mapping_gfp_mask(void)
0151 {
0152     return GFP_HIGHUSER;
0153 }
0154 
0155 #endif /* CONFIG_BALLOON_COMPACTION */
0156 
0157 /*
0158  * balloon_page_push - insert a page into a page list.
0159  * @head : pointer to list
0160  * @page : page to be added
0161  *
0162  * Caller must ensure the page is private and protect the list.
0163  */
0164 static inline void balloon_page_push(struct list_head *pages, struct page *page)
0165 {
0166     list_add(&page->lru, pages);
0167 }
0168 
0169 /*
0170  * balloon_page_pop - remove a page from a page list.
0171  * @head : pointer to list
0172  * @page : page to be added
0173  *
0174  * Caller must ensure the page is private and protect the list.
0175  */
0176 static inline struct page *balloon_page_pop(struct list_head *pages)
0177 {
0178     struct page *page = list_first_entry_or_null(pages, struct page, lru);
0179 
0180     if (!page)
0181         return NULL;
0182 
0183     list_del(&page->lru);
0184     return page;
0185 }
0186 #endif /* _LINUX_BALLOON_COMPACTION_H */