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