1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* zpdesc.h: zswap.zpool memory descriptor
3  *
4  * Written by Alex Shi <[email protected]>
5  *	      Hyeonggon Yoo <[email protected]>
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 
zpdesc_lock(struct zpdesc * zpdesc)107 static inline void zpdesc_lock(struct zpdesc *zpdesc)
108 {
109 	folio_lock(zpdesc_folio(zpdesc));
110 }
111 
zpdesc_trylock(struct zpdesc * zpdesc)112 static inline bool zpdesc_trylock(struct zpdesc *zpdesc)
113 {
114 	return folio_trylock(zpdesc_folio(zpdesc));
115 }
116 
zpdesc_unlock(struct zpdesc * zpdesc)117 static inline void zpdesc_unlock(struct zpdesc *zpdesc)
118 {
119 	folio_unlock(zpdesc_folio(zpdesc));
120 }
121 
zpdesc_wait_locked(struct zpdesc * zpdesc)122 static inline void zpdesc_wait_locked(struct zpdesc *zpdesc)
123 {
124 	folio_wait_locked(zpdesc_folio(zpdesc));
125 }
126 
zpdesc_get(struct zpdesc * zpdesc)127 static inline void zpdesc_get(struct zpdesc *zpdesc)
128 {
129 	folio_get(zpdesc_folio(zpdesc));
130 }
131 
zpdesc_put(struct zpdesc * zpdesc)132 static inline void zpdesc_put(struct zpdesc *zpdesc)
133 {
134 	folio_put(zpdesc_folio(zpdesc));
135 }
136 
kmap_local_zpdesc(struct zpdesc * zpdesc)137 static inline void *kmap_local_zpdesc(struct zpdesc *zpdesc)
138 {
139 	return kmap_local_page(zpdesc_page(zpdesc));
140 }
141 
zpdesc_pfn(struct zpdesc * zpdesc)142 static inline unsigned long zpdesc_pfn(struct zpdesc *zpdesc)
143 {
144 	return page_to_pfn(zpdesc_page(zpdesc));
145 }
146 
pfn_zpdesc(unsigned long pfn)147 static inline struct zpdesc *pfn_zpdesc(unsigned long pfn)
148 {
149 	return page_zpdesc(pfn_to_page(pfn));
150 }
151 
__zpdesc_set_movable(struct zpdesc * zpdesc,const struct movable_operations * mops)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 
__zpdesc_set_zsmalloc(struct zpdesc * zpdesc)158 static inline void __zpdesc_set_zsmalloc(struct zpdesc *zpdesc)
159 {
160 	__SetPageZsmalloc(zpdesc_page(zpdesc));
161 }
162 
__zpdesc_clear_zsmalloc(struct zpdesc * zpdesc)163 static inline void __zpdesc_clear_zsmalloc(struct zpdesc *zpdesc)
164 {
165 	__ClearPageZsmalloc(zpdesc_page(zpdesc));
166 }
167 
zpdesc_is_isolated(struct zpdesc * zpdesc)168 static inline bool zpdesc_is_isolated(struct zpdesc *zpdesc)
169 {
170 	return PageIsolated(zpdesc_page(zpdesc));
171 }
172 
zpdesc_zone(struct zpdesc * zpdesc)173 static inline struct zone *zpdesc_zone(struct zpdesc *zpdesc)
174 {
175 	return page_zone(zpdesc_page(zpdesc));
176 }
177 
zpdesc_is_locked(struct zpdesc * zpdesc)178 static inline bool zpdesc_is_locked(struct zpdesc *zpdesc)
179 {
180 	return folio_test_locked(zpdesc_folio(zpdesc));
181 }
182 #endif
183