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