1 #ifndef _LINUX_SWAPOPS_H 2 #define _LINUX_SWAPOPS_H 3 4 #include <linux/radix-tree.h> 5 #include <linux/bug.h> 6 7 /* 8 * swapcache pages are stored in the swapper_space radix tree. We want to 9 * get good packing density in that tree, so the index should be dense in 10 * the low-order bits. 11 * 12 * We arrange the `type' and `offset' fields so that `type' is at the five 13 * high-order bits of the swp_entry_t and `offset' is right-aligned in the 14 * remaining bits. 15 * 16 * swp_entry_t's are *never* stored anywhere in their arch-dependent format. 17 */ 18 #define SWP_TYPE_SHIFT(e) (sizeof(e.val) * 8 - MAX_SWAPFILES_SHIFT) 19 #define SWP_OFFSET_MASK(e) ((1UL << SWP_TYPE_SHIFT(e)) - 1) 20 21 /* 22 * Store a type+offset into a swp_entry_t in an arch-independent format 23 */ 24 static inline swp_entry_t swp_entry(unsigned long type, pgoff_t offset) 25 { 26 swp_entry_t ret; 27 28 ret.val = (type << SWP_TYPE_SHIFT(ret)) | 29 (offset & SWP_OFFSET_MASK(ret)); 30 return ret; 31 } 32 33 /* 34 * Extract the `type' field from a swp_entry_t. The swp_entry_t is in 35 * arch-independent format 36 */ 37 static inline unsigned swp_type(swp_entry_t entry) 38 { 39 return (entry.val >> SWP_TYPE_SHIFT(entry)); 40 } 41 42 /* 43 * Extract the `offset' field from a swp_entry_t. The swp_entry_t is in 44 * arch-independent format 45 */ 46 static inline pgoff_t swp_offset(swp_entry_t entry) 47 { 48 return entry.val & SWP_OFFSET_MASK(entry); 49 } 50 51 #ifdef CONFIG_MMU 52 /* check whether a pte points to a swap entry */ 53 static inline int is_swap_pte(pte_t pte) 54 { 55 return !pte_none(pte) && !pte_present(pte) && !pte_file(pte); 56 } 57 #endif 58 59 /* 60 * Convert the arch-dependent pte representation of a swp_entry_t into an 61 * arch-independent swp_entry_t. 62 */ 63 static inline swp_entry_t pte_to_swp_entry(pte_t pte) 64 { 65 swp_entry_t arch_entry; 66 67 BUG_ON(pte_file(pte)); 68 arch_entry = __pte_to_swp_entry(pte); 69 return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry)); 70 } 71 72 /* 73 * Convert the arch-independent representation of a swp_entry_t into the 74 * arch-dependent pte representation. 75 */ 76 static inline pte_t swp_entry_to_pte(swp_entry_t entry) 77 { 78 swp_entry_t arch_entry; 79 80 arch_entry = __swp_entry(swp_type(entry), swp_offset(entry)); 81 BUG_ON(pte_file(__swp_entry_to_pte(arch_entry))); 82 return __swp_entry_to_pte(arch_entry); 83 } 84 85 static inline swp_entry_t radix_to_swp_entry(void *arg) 86 { 87 swp_entry_t entry; 88 89 entry.val = (unsigned long)arg >> RADIX_TREE_EXCEPTIONAL_SHIFT; 90 return entry; 91 } 92 93 static inline void *swp_to_radix_entry(swp_entry_t entry) 94 { 95 unsigned long value; 96 97 value = entry.val << RADIX_TREE_EXCEPTIONAL_SHIFT; 98 return (void *)(value | RADIX_TREE_EXCEPTIONAL_ENTRY); 99 } 100 101 #ifdef CONFIG_MIGRATION 102 static inline swp_entry_t make_migration_entry(struct page *page, int write) 103 { 104 BUG_ON(!PageLocked(page)); 105 return swp_entry(write ? SWP_MIGRATION_WRITE : SWP_MIGRATION_READ, 106 page_to_pfn(page)); 107 } 108 109 static inline int is_migration_entry(swp_entry_t entry) 110 { 111 return unlikely(swp_type(entry) == SWP_MIGRATION_READ || 112 swp_type(entry) == SWP_MIGRATION_WRITE); 113 } 114 115 static inline int is_write_migration_entry(swp_entry_t entry) 116 { 117 return unlikely(swp_type(entry) == SWP_MIGRATION_WRITE); 118 } 119 120 static inline struct page *migration_entry_to_page(swp_entry_t entry) 121 { 122 struct page *p = pfn_to_page(swp_offset(entry)); 123 /* 124 * Any use of migration entries may only occur while the 125 * corresponding page is locked 126 */ 127 BUG_ON(!PageLocked(p)); 128 return p; 129 } 130 131 static inline void make_migration_entry_read(swp_entry_t *entry) 132 { 133 *entry = swp_entry(SWP_MIGRATION_READ, swp_offset(*entry)); 134 } 135 136 extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, 137 unsigned long address); 138 #else 139 140 #define make_migration_entry(page, write) swp_entry(0, 0) 141 static inline int is_migration_entry(swp_entry_t swp) 142 { 143 return 0; 144 } 145 #define migration_entry_to_page(swp) NULL 146 static inline void make_migration_entry_read(swp_entry_t *entryp) { } 147 static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, 148 unsigned long address) { } 149 static inline int is_write_migration_entry(swp_entry_t entry) 150 { 151 return 0; 152 } 153 154 #endif 155 156 #ifdef CONFIG_MEMORY_FAILURE 157 /* 158 * Support for hardware poisoned pages 159 */ 160 static inline swp_entry_t make_hwpoison_entry(struct page *page) 161 { 162 BUG_ON(!PageLocked(page)); 163 return swp_entry(SWP_HWPOISON, page_to_pfn(page)); 164 } 165 166 static inline int is_hwpoison_entry(swp_entry_t entry) 167 { 168 return swp_type(entry) == SWP_HWPOISON; 169 } 170 #else 171 172 static inline swp_entry_t make_hwpoison_entry(struct page *page) 173 { 174 return swp_entry(0, 0); 175 } 176 177 static inline int is_hwpoison_entry(swp_entry_t swp) 178 { 179 return 0; 180 } 181 #endif 182 183 #if defined(CONFIG_MEMORY_FAILURE) || defined(CONFIG_MIGRATION) 184 static inline int non_swap_entry(swp_entry_t entry) 185 { 186 return swp_type(entry) >= MAX_SWAPFILES; 187 } 188 #else 189 static inline int non_swap_entry(swp_entry_t entry) 190 { 191 return 0; 192 } 193 #endif 194 195 #endif /* _LINUX_SWAPOPS_H */ 196