1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* zpdesc.h: zswap.zpool memory descriptor 3 * 4 * Written by Alex Shi <alexs@kernel.org> 5 * Hyeonggon Yoo <42.hyeyoo@gmail.com> 6 */ 7 #ifndef __MM_ZPDESC_H__ 8 #define __MM_ZPDESC_H__ 9 10 /* 11 * struct zpdesc - Memory descriptor for zpool memory. 12 * @flags: Page flags, mostly unused by zsmalloc. 13 * @lru: Indirectly used by page migration. 14 * @movable_ops: Used by page migration. 15 * @next: Next zpdesc in a zspage in zsmalloc zpool. 16 * @handle: For huge zspage in zsmalloc zpool. 17 * @zspage: Points to the zspage this zpdesc is a part of. 18 * @first_obj_offset: First object offset in zsmalloc zpool. 19 * @_refcount: The number of references to this zpdesc. 20 * 21 * This struct overlays struct page for now. Do not modify without a good 22 * understanding of the issues. In particular, do not expand into the overlap 23 * with memcg_data. 24 * 25 * Page flags used: 26 * * PG_private identifies the first component page. 27 * * PG_locked is used by page migration code. 28 */ 29 struct zpdesc { 30 unsigned long flags; 31 struct list_head lru; 32 unsigned long movable_ops; 33 union { 34 struct zpdesc *next; 35 unsigned long handle; 36 }; 37 struct zspage *zspage; 38 /* 39 * Only the lower 24 bits are available for offset, limiting a page 40 * to 16 MiB. The upper 8 bits are reserved for PGTY_zsmalloc. 41 * 42 * Do not access this field directly. 43 * Instead, use {get,set}_first_obj_offset() helpers. 44 */ 45 unsigned int first_obj_offset; 46 atomic_t _refcount; 47 }; 48 #define ZPDESC_MATCH(pg, zp) \ 49 static_assert(offsetof(struct page, pg) == offsetof(struct zpdesc, zp)) 50 51 ZPDESC_MATCH(flags, flags); 52 ZPDESC_MATCH(lru, lru); 53 ZPDESC_MATCH(mapping, movable_ops); 54 ZPDESC_MATCH(index, next); 55 ZPDESC_MATCH(index, handle); 56 ZPDESC_MATCH(private, zspage); 57 ZPDESC_MATCH(page_type, first_obj_offset); 58 ZPDESC_MATCH(_refcount, _refcount); 59 #undef ZPDESC_MATCH 60 static_assert(sizeof(struct zpdesc) <= sizeof(struct page)); 61 62 /* 63 * zpdesc_page - The first struct page allocated for a zpdesc 64 * @zp: The zpdesc. 65 * 66 * A convenience wrapper for converting zpdesc to the first struct page of the 67 * underlying folio, to communicate with code not yet converted to folio or 68 * struct zpdesc. 69 * 70 */ 71 #define zpdesc_page(zp) (_Generic((zp), \ 72 const struct zpdesc *: (const struct page *)(zp), \ 73 struct zpdesc *: (struct page *)(zp))) 74 75 /** 76 * zpdesc_folio - The folio allocated for a zpdesc 77 * @zp: The zpdesc. 78 * 79 * Zpdescs are descriptors for zpool memory. The zpool memory itself is 80 * allocated as folios that contain the zpool objects, and zpdesc uses specific 81 * fields in the first struct page of the folio - those fields are now accessed 82 * by struct zpdesc. 83 * 84 * It is occasionally necessary convert to back to a folio in order to 85 * communicate with the rest of the mm. Please use this helper function 86 * instead of casting yourself, as the implementation may change in the future. 87 */ 88 #define zpdesc_folio(zp) (_Generic((zp), \ 89 const struct zpdesc *: (const struct folio *)(zp), \ 90 struct zpdesc *: (struct folio *)(zp))) 91 /** 92 * page_zpdesc - Converts from first struct page to zpdesc. 93 * @p: The first (either head of compound or single) page of zpdesc. 94 * 95 * A temporary wrapper to convert struct page to struct zpdesc in situations 96 * where we know the page is the compound head, or single order-0 page. 97 * 98 * Long-term ideally everything would work with struct zpdesc directly or go 99 * through folio to struct zpdesc. 100 * 101 * Return: The zpdesc which contains this page 102 */ 103 #define page_zpdesc(p) (_Generic((p), \ 104 const struct page *: (const struct zpdesc *)(p), \ 105 struct page *: (struct zpdesc *)(p))) 106 107 static inline void zpdesc_lock(struct zpdesc *zpdesc) 108 { 109 folio_lock(zpdesc_folio(zpdesc)); 110 } 111 112 static inline bool zpdesc_trylock(struct zpdesc *zpdesc) 113 { 114 return folio_trylock(zpdesc_folio(zpdesc)); 115 } 116 117 static inline void zpdesc_unlock(struct zpdesc *zpdesc) 118 { 119 folio_unlock(zpdesc_folio(zpdesc)); 120 } 121 122 static inline void zpdesc_wait_locked(struct zpdesc *zpdesc) 123 { 124 folio_wait_locked(zpdesc_folio(zpdesc)); 125 } 126 127 static inline void zpdesc_get(struct zpdesc *zpdesc) 128 { 129 folio_get(zpdesc_folio(zpdesc)); 130 } 131 132 static inline void zpdesc_put(struct zpdesc *zpdesc) 133 { 134 folio_put(zpdesc_folio(zpdesc)); 135 } 136 137 static inline void *kmap_local_zpdesc(struct zpdesc *zpdesc) 138 { 139 return kmap_local_page(zpdesc_page(zpdesc)); 140 } 141 142 static inline unsigned long zpdesc_pfn(struct zpdesc *zpdesc) 143 { 144 return page_to_pfn(zpdesc_page(zpdesc)); 145 } 146 147 static inline struct zpdesc *pfn_zpdesc(unsigned long pfn) 148 { 149 return page_zpdesc(pfn_to_page(pfn)); 150 } 151 152 static inline void __zpdesc_set_movable(struct zpdesc *zpdesc, 153 const struct movable_operations *mops) 154 { 155 __SetPageMovable(zpdesc_page(zpdesc), mops); 156 } 157 158 static inline void __zpdesc_set_zsmalloc(struct zpdesc *zpdesc) 159 { 160 __SetPageZsmalloc(zpdesc_page(zpdesc)); 161 } 162 163 static inline void __zpdesc_clear_zsmalloc(struct zpdesc *zpdesc) 164 { 165 __ClearPageZsmalloc(zpdesc_page(zpdesc)); 166 } 167 168 static inline bool zpdesc_is_isolated(struct zpdesc *zpdesc) 169 { 170 return PageIsolated(zpdesc_page(zpdesc)); 171 } 172 173 static inline struct zone *zpdesc_zone(struct zpdesc *zpdesc) 174 { 175 return page_zone(zpdesc_page(zpdesc)); 176 } 177 178 static inline bool zpdesc_is_locked(struct zpdesc *zpdesc) 179 { 180 return folio_test_locked(zpdesc_folio(zpdesc)); 181 } 182 #endif 183