LCOV - code coverage report
Current view: top level - include/linux - balloon_compaction.h (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 24 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : /*
       3             :  * include/linux/balloon_compaction.h
       4             :  *
       5             :  * Common interface definitions for making balloon pages movable by compaction.
       6             :  *
       7             :  * Balloon page migration makes use of the general non-lru movable page
       8             :  * feature.
       9             :  *
      10             :  * page->private is used to reference the responsible balloon device.
      11             :  * page->mapping is used in context of non-lru page migration to reference
      12             :  * the address space operations for page isolation/migration/compaction.
      13             :  *
      14             :  * As the page isolation scanning step a compaction thread does is a lockless
      15             :  * procedure (from a page standpoint), it might bring some racy situations while
      16             :  * performing balloon page compaction. In order to sort out these racy scenarios
      17             :  * and safely perform balloon's page compaction and migration we must, always,
      18             :  * ensure following these simple rules:
      19             :  *
      20             :  *   i. when updating a balloon's page ->mapping element, strictly do it under
      21             :  *      the following lock order, independently of the far superior
      22             :  *      locking scheme (lru_lock, balloon_lock):
      23             :  *          +-page_lock(page);
      24             :  *            +--spin_lock_irq(&b_dev_info->pages_lock);
      25             :  *                  ... page->mapping updates here ...
      26             :  *
      27             :  *  ii. isolation or dequeueing procedure must remove the page from balloon
      28             :  *      device page list under b_dev_info->pages_lock.
      29             :  *
      30             :  * The functions provided by this interface are placed to help on coping with
      31             :  * the aforementioned balloon page corner case, as well as to ensure the simple
      32             :  * set of exposed rules are satisfied while we are dealing with balloon pages
      33             :  * compaction / migration.
      34             :  *
      35             :  * Copyright (C) 2012, Red Hat, Inc.  Rafael Aquini <aquini@redhat.com>
      36             :  */
      37             : #ifndef _LINUX_BALLOON_COMPACTION_H
      38             : #define _LINUX_BALLOON_COMPACTION_H
      39             : #include <linux/pagemap.h>
      40             : #include <linux/page-flags.h>
      41             : #include <linux/migrate.h>
      42             : #include <linux/gfp.h>
      43             : #include <linux/err.h>
      44             : #include <linux/fs.h>
      45             : #include <linux/list.h>
      46             : 
      47             : /*
      48             :  * Balloon device information descriptor.
      49             :  * This struct is used to allow the common balloon compaction interface
      50             :  * procedures to find the proper balloon device holding memory pages they'll
      51             :  * have to cope for page compaction / migration, as well as it serves the
      52             :  * balloon driver as a page book-keeper for its registered balloon devices.
      53             :  */
      54             : struct balloon_dev_info {
      55             :         unsigned long isolated_pages;   /* # of isolated pages for migration */
      56             :         spinlock_t pages_lock;          /* Protection to pages list */
      57             :         struct list_head pages;         /* Pages enqueued & handled to Host */
      58             :         int (*migratepage)(struct balloon_dev_info *, struct page *newpage,
      59             :                         struct page *page, enum migrate_mode mode);
      60             :         struct inode *inode;
      61             : };
      62             : 
      63             : extern struct page *balloon_page_alloc(void);
      64             : extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
      65             :                                  struct page *page);
      66             : extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
      67             : extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
      68             :                                       struct list_head *pages);
      69             : extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
      70             :                                      struct list_head *pages, size_t n_req_pages);
      71             : 
      72           0 : static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
      73             : {
      74           0 :         balloon->isolated_pages = 0;
      75           0 :         spin_lock_init(&balloon->pages_lock);
      76           0 :         INIT_LIST_HEAD(&balloon->pages);
      77           0 :         balloon->migratepage = NULL;
      78           0 :         balloon->inode = NULL;
      79           0 : }
      80             : 
      81             : #ifdef CONFIG_BALLOON_COMPACTION
      82             : extern const struct address_space_operations balloon_aops;
      83             : extern bool balloon_page_isolate(struct page *page,
      84             :                                 isolate_mode_t mode);
      85             : extern void balloon_page_putback(struct page *page);
      86             : extern int balloon_page_migrate(struct address_space *mapping,
      87             :                                 struct page *newpage,
      88             :                                 struct page *page, enum migrate_mode mode);
      89             : 
      90             : /*
      91             :  * balloon_page_insert - insert a page into the balloon's page list and make
      92             :  *                       the page->private assignment accordingly.
      93             :  * @balloon : pointer to balloon device
      94             :  * @page    : page to be assigned as a 'balloon page'
      95             :  *
      96             :  * Caller must ensure the page is locked and the spin_lock protecting balloon
      97             :  * pages list is held before inserting a page into the balloon device.
      98             :  */
      99             : static inline void balloon_page_insert(struct balloon_dev_info *balloon,
     100             :                                        struct page *page)
     101             : {
     102             :         __SetPageOffline(page);
     103             :         __SetPageMovable(page, balloon->inode->i_mapping);
     104             :         set_page_private(page, (unsigned long)balloon);
     105             :         list_add(&page->lru, &balloon->pages);
     106             : }
     107             : 
     108             : /*
     109             :  * balloon_page_delete - delete a page from balloon's page list and clear
     110             :  *                       the page->private assignement accordingly.
     111             :  * @page    : page to be released from balloon's page list
     112             :  *
     113             :  * Caller must ensure the page is locked and the spin_lock protecting balloon
     114             :  * pages list is held before deleting a page from the balloon device.
     115             :  */
     116             : static inline void balloon_page_delete(struct page *page)
     117             : {
     118             :         __ClearPageOffline(page);
     119             :         __ClearPageMovable(page);
     120             :         set_page_private(page, 0);
     121             :         /*
     122             :          * No touch page.lru field once @page has been isolated
     123             :          * because VM is using the field.
     124             :          */
     125             :         if (!PageIsolated(page))
     126             :                 list_del(&page->lru);
     127             : }
     128             : 
     129             : /*
     130             :  * balloon_page_device - get the b_dev_info descriptor for the balloon device
     131             :  *                       that enqueues the given page.
     132             :  */
     133             : static inline struct balloon_dev_info *balloon_page_device(struct page *page)
     134             : {
     135             :         return (struct balloon_dev_info *)page_private(page);
     136             : }
     137             : 
     138             : static inline gfp_t balloon_mapping_gfp_mask(void)
     139             : {
     140             :         return GFP_HIGHUSER_MOVABLE;
     141             : }
     142             : 
     143             : #else /* !CONFIG_BALLOON_COMPACTION */
     144             : 
     145           0 : static inline void balloon_page_insert(struct balloon_dev_info *balloon,
     146             :                                        struct page *page)
     147             : {
     148           0 :         __SetPageOffline(page);
     149           0 :         list_add(&page->lru, &balloon->pages);
     150           0 : }
     151             : 
     152           0 : static inline void balloon_page_delete(struct page *page)
     153             : {
     154           0 :         __ClearPageOffline(page);
     155           0 :         list_del(&page->lru);
     156           0 : }
     157             : 
     158             : static inline bool balloon_page_isolate(struct page *page)
     159             : {
     160             :         return false;
     161             : }
     162             : 
     163             : static inline void balloon_page_putback(struct page *page)
     164             : {
     165             :         return;
     166             : }
     167             : 
     168             : static inline int balloon_page_migrate(struct page *newpage,
     169             :                                 struct page *page, enum migrate_mode mode)
     170             : {
     171             :         return 0;
     172             : }
     173             : 
     174           0 : static inline gfp_t balloon_mapping_gfp_mask(void)
     175             : {
     176           0 :         return GFP_HIGHUSER;
     177             : }
     178             : 
     179             : #endif /* CONFIG_BALLOON_COMPACTION */
     180             : 
     181             : /*
     182             :  * balloon_page_push - insert a page into a page list.
     183             :  * @head : pointer to list
     184             :  * @page : page to be added
     185             :  *
     186             :  * Caller must ensure the page is private and protect the list.
     187             :  */
     188           0 : static inline void balloon_page_push(struct list_head *pages, struct page *page)
     189             : {
     190           0 :         list_add(&page->lru, pages);
     191             : }
     192             : 
     193             : /*
     194             :  * balloon_page_pop - remove a page from a page list.
     195             :  * @head : pointer to list
     196             :  * @page : page to be added
     197             :  *
     198             :  * Caller must ensure the page is private and protect the list.
     199             :  */
     200           0 : static inline struct page *balloon_page_pop(struct list_head *pages)
     201             : {
     202           0 :         struct page *page = list_first_entry_or_null(pages, struct page, lru);
     203             : 
     204           0 :         if (!page)
     205             :                 return NULL;
     206             : 
     207           0 :         list_del(&page->lru);
     208           0 :         return page;
     209             : }
     210             : #endif /* _LINUX_BALLOON_COMPACTION_H */

Generated by: LCOV version 1.14