Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : #ifndef _LINUX_MIGRATE_H 3 : : #define _LINUX_MIGRATE_H 4 : : 5 : : #include <linux/mm.h> 6 : : #include <linux/mempolicy.h> 7 : : #include <linux/migrate_mode.h> 8 : : #include <linux/hugetlb.h> 9 : : 10 : : typedef struct page *new_page_t(struct page *page, unsigned long private); 11 : : typedef void free_page_t(struct page *page, unsigned long private); 12 : : 13 : : /* 14 : : * Return values from addresss_space_operations.migratepage(): 15 : : * - negative errno on page migration failure; 16 : : * - zero on page migration success; 17 : : */ 18 : : #define MIGRATEPAGE_SUCCESS 0 19 : : 20 : : enum migrate_reason { 21 : : MR_COMPACTION, 22 : : MR_MEMORY_FAILURE, 23 : : MR_MEMORY_HOTPLUG, 24 : : MR_SYSCALL, /* also applies to cpusets */ 25 : : MR_MEMPOLICY_MBIND, 26 : : MR_NUMA_MISPLACED, 27 : : MR_CONTIG_RANGE, 28 : : MR_TYPES 29 : : }; 30 : : 31 : : /* In mm/debug.c; also keep sync with include/trace/events/migrate.h */ 32 : : extern const char *migrate_reason_names[MR_TYPES]; 33 : : 34 : 0 : static inline struct page *new_page_nodemask(struct page *page, 35 : : int preferred_nid, nodemask_t *nodemask) 36 : : { 37 : : gfp_t gfp_mask = GFP_USER | __GFP_MOVABLE | __GFP_RETRY_MAYFAIL; 38 : : unsigned int order = 0; 39 : : struct page *new_page = NULL; 40 : : 41 : : if (PageHuge(page)) 42 : : return alloc_huge_page_nodemask(page_hstate(compound_head(page)), 43 : : preferred_nid, nodemask); 44 : : 45 : : if (PageTransHuge(page)) { 46 : : gfp_mask |= GFP_TRANSHUGE; 47 : : order = HPAGE_PMD_ORDER; 48 : : } 49 : : 50 : 0 : if (PageHighMem(page) || (zone_idx(page_zone(page)) == ZONE_MOVABLE)) 51 : : gfp_mask |= __GFP_HIGHMEM; 52 : : 53 : 0 : new_page = __alloc_pages_nodemask(gfp_mask, order, 54 : : preferred_nid, nodemask); 55 : : 56 : : if (new_page && PageTransHuge(new_page)) 57 : : prep_transhuge_page(new_page); 58 : : 59 : : return new_page; 60 : : } 61 : : 62 : : #ifdef CONFIG_MIGRATION 63 : : 64 : : extern void putback_movable_pages(struct list_head *l); 65 : : extern int migrate_page(struct address_space *mapping, 66 : : struct page *newpage, struct page *page, 67 : : enum migrate_mode mode); 68 : : extern int migrate_pages(struct list_head *l, new_page_t new, free_page_t free, 69 : : unsigned long private, enum migrate_mode mode, int reason); 70 : : extern int isolate_movable_page(struct page *page, isolate_mode_t mode); 71 : : extern void putback_movable_page(struct page *page); 72 : : 73 : : extern int migrate_prep(void); 74 : : extern int migrate_prep_local(void); 75 : : extern void migrate_page_states(struct page *newpage, struct page *page); 76 : : extern void migrate_page_copy(struct page *newpage, struct page *page); 77 : : extern int migrate_huge_page_move_mapping(struct address_space *mapping, 78 : : struct page *newpage, struct page *page); 79 : : extern int migrate_page_move_mapping(struct address_space *mapping, 80 : : struct page *newpage, struct page *page, int extra_count); 81 : : #else 82 : : 83 : : static inline void putback_movable_pages(struct list_head *l) {} 84 : : static inline int migrate_pages(struct list_head *l, new_page_t new, 85 : : free_page_t free, unsigned long private, enum migrate_mode mode, 86 : : int reason) 87 : : { return -ENOSYS; } 88 : : static inline int isolate_movable_page(struct page *page, isolate_mode_t mode) 89 : : { return -EBUSY; } 90 : : 91 : : static inline int migrate_prep(void) { return -ENOSYS; } 92 : : static inline int migrate_prep_local(void) { return -ENOSYS; } 93 : : 94 : : static inline void migrate_page_states(struct page *newpage, struct page *page) 95 : : { 96 : : } 97 : : 98 : : static inline void migrate_page_copy(struct page *newpage, 99 : : struct page *page) {} 100 : : 101 : : static inline int migrate_huge_page_move_mapping(struct address_space *mapping, 102 : : struct page *newpage, struct page *page) 103 : : { 104 : : return -ENOSYS; 105 : : } 106 : : 107 : : #endif /* CONFIG_MIGRATION */ 108 : : 109 : : #ifdef CONFIG_COMPACTION 110 : : extern int PageMovable(struct page *page); 111 : : extern void __SetPageMovable(struct page *page, struct address_space *mapping); 112 : : extern void __ClearPageMovable(struct page *page); 113 : : #else 114 : : static inline int PageMovable(struct page *page) { return 0; }; 115 : : static inline void __SetPageMovable(struct page *page, 116 : : struct address_space *mapping) 117 : : { 118 : : } 119 : : static inline void __ClearPageMovable(struct page *page) 120 : : { 121 : : } 122 : : #endif 123 : : 124 : : #ifdef CONFIG_NUMA_BALANCING 125 : : extern bool pmd_trans_migrating(pmd_t pmd); 126 : : extern int migrate_misplaced_page(struct page *page, 127 : : struct vm_area_struct *vma, int node); 128 : : #else 129 : : static inline bool pmd_trans_migrating(pmd_t pmd) 130 : : { 131 : : return false; 132 : : } 133 : : static inline int migrate_misplaced_page(struct page *page, 134 : : struct vm_area_struct *vma, int node) 135 : : { 136 : : return -EAGAIN; /* can't migrate now */ 137 : : } 138 : : #endif /* CONFIG_NUMA_BALANCING */ 139 : : 140 : : #if defined(CONFIG_NUMA_BALANCING) && defined(CONFIG_TRANSPARENT_HUGEPAGE) 141 : : extern int migrate_misplaced_transhuge_page(struct mm_struct *mm, 142 : : struct vm_area_struct *vma, 143 : : pmd_t *pmd, pmd_t entry, 144 : : unsigned long address, 145 : : struct page *page, int node); 146 : : #else 147 : : static inline int migrate_misplaced_transhuge_page(struct mm_struct *mm, 148 : : struct vm_area_struct *vma, 149 : : pmd_t *pmd, pmd_t entry, 150 : : unsigned long address, 151 : : struct page *page, int node) 152 : : { 153 : : return -EAGAIN; 154 : : } 155 : : #endif /* CONFIG_NUMA_BALANCING && CONFIG_TRANSPARENT_HUGEPAGE*/ 156 : : 157 : : 158 : : #ifdef CONFIG_MIGRATION 159 : : 160 : : /* 161 : : * Watch out for PAE architecture, which has an unsigned long, and might not 162 : : * have enough bits to store all physical address and flags. So far we have 163 : : * enough room for all our flags. 164 : : */ 165 : : #define MIGRATE_PFN_VALID (1UL << 0) 166 : : #define MIGRATE_PFN_MIGRATE (1UL << 1) 167 : : #define MIGRATE_PFN_LOCKED (1UL << 2) 168 : : #define MIGRATE_PFN_WRITE (1UL << 3) 169 : : #define MIGRATE_PFN_SHIFT 6 170 : : 171 : : static inline struct page *migrate_pfn_to_page(unsigned long mpfn) 172 : : { 173 : : if (!(mpfn & MIGRATE_PFN_VALID)) 174 : : return NULL; 175 : : return pfn_to_page(mpfn >> MIGRATE_PFN_SHIFT); 176 : : } 177 : : 178 : : static inline unsigned long migrate_pfn(unsigned long pfn) 179 : : { 180 : : return (pfn << MIGRATE_PFN_SHIFT) | MIGRATE_PFN_VALID; 181 : : } 182 : : 183 : : struct migrate_vma { 184 : : struct vm_area_struct *vma; 185 : : /* 186 : : * Both src and dst array must be big enough for 187 : : * (end - start) >> PAGE_SHIFT entries. 188 : : * 189 : : * The src array must not be modified by the caller after 190 : : * migrate_vma_setup(), and must not change the dst array after 191 : : * migrate_vma_pages() returns. 192 : : */ 193 : : unsigned long *dst; 194 : : unsigned long *src; 195 : : unsigned long cpages; 196 : : unsigned long npages; 197 : : unsigned long start; 198 : : unsigned long end; 199 : : }; 200 : : 201 : : int migrate_vma_setup(struct migrate_vma *args); 202 : : void migrate_vma_pages(struct migrate_vma *migrate); 203 : : void migrate_vma_finalize(struct migrate_vma *migrate); 204 : : 205 : : #endif /* CONFIG_MIGRATION */ 206 : : 207 : : #endif /* _LINUX_MIGRATE_H */