at v3.4 4.8 kB view raw
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 */ 24static 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 */ 37static 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 */ 46static 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 */ 53static 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 */ 63static 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 */ 76static 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 85static 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 93static 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 102static 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 109static 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 115static inline int is_write_migration_entry(swp_entry_t entry) 116{ 117 return unlikely(swp_type(entry) == SWP_MIGRATION_WRITE); 118} 119 120static 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 131static inline void make_migration_entry_read(swp_entry_t *entry) 132{ 133 *entry = swp_entry(SWP_MIGRATION_READ, swp_offset(*entry)); 134} 135 136extern 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) 141static inline int is_migration_entry(swp_entry_t swp) 142{ 143 return 0; 144} 145#define migration_entry_to_page(swp) NULL 146static inline void make_migration_entry_read(swp_entry_t *entryp) { } 147static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, 148 unsigned long address) { } 149static 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 */ 160static 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 166static inline int is_hwpoison_entry(swp_entry_t entry) 167{ 168 return swp_type(entry) == SWP_HWPOISON; 169} 170#else 171 172static inline swp_entry_t make_hwpoison_entry(struct page *page) 173{ 174 return swp_entry(0, 0); 175} 176 177static 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) 184static inline int non_swap_entry(swp_entry_t entry) 185{ 186 return swp_type(entry) >= MAX_SWAPFILES; 187} 188#else 189static inline int non_swap_entry(swp_entry_t entry) 190{ 191 return 0; 192} 193#endif 194 195#endif /* _LINUX_SWAPOPS_H */