File Index
Files and directories
Sign in
FILE

zpdesc.h

File preview with syntax highlighting.

linux-6.19.14/mm/zpdesc.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/* zpdesc.h: zsmalloc pool 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 zsmalloc pool 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 pool.
 19 * @handle:		For huge zspage in zsmalloc pool.
 20 * @zspage:		Points to the zspage this zpdesc is a part of.
 21 * @first_obj_offset:	First object offset in zsmalloc pool.
 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 */
 32struct 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
 54ZPDESC_MATCH(flags, flags);
 55ZPDESC_MATCH(lru, lru);
 56ZPDESC_MATCH(mapping, movable_ops);
 57ZPDESC_MATCH(__folio_index, next);
 58ZPDESC_MATCH(__folio_index, handle);
 59ZPDESC_MATCH(private, zspage);
 60ZPDESC_MATCH(page_type, first_obj_offset);
 61ZPDESC_MATCH(_refcount, _refcount);
 62#undef ZPDESC_MATCH
 63static_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 zsmalloc memory. The memory itself is allocated
 83 * as folios that contain the zsmalloc 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
110static inline void zpdesc_lock(struct zpdesc *zpdesc)
111{
112	folio_lock(zpdesc_folio(zpdesc));
113}
114
115static inline bool zpdesc_trylock(struct zpdesc *zpdesc)
116{
117	return folio_trylock(zpdesc_folio(zpdesc));
118}
119
120static inline void zpdesc_unlock(struct zpdesc *zpdesc)
121{
122	folio_unlock(zpdesc_folio(zpdesc));
123}
124
125static inline void zpdesc_wait_locked(struct zpdesc *zpdesc)
126{
127	folio_wait_locked(zpdesc_folio(zpdesc));
128}
129
130static inline void zpdesc_get(struct zpdesc *zpdesc)
131{
132	folio_get(zpdesc_folio(zpdesc));
133}
134
135static inline void zpdesc_put(struct zpdesc *zpdesc)
136{
137	folio_put(zpdesc_folio(zpdesc));
138}
139
140static inline void *kmap_local_zpdesc(struct zpdesc *zpdesc)
141{
142	return kmap_local_page(zpdesc_page(zpdesc));
143}
144
145static inline unsigned long zpdesc_pfn(struct zpdesc *zpdesc)
146{
147	return page_to_pfn(zpdesc_page(zpdesc));
148}
149
150static inline struct zpdesc *pfn_zpdesc(unsigned long pfn)
151{
152	return page_zpdesc(pfn_to_page(pfn));
153}
154
155static inline void __zpdesc_set_movable(struct zpdesc *zpdesc)
156{
157	SetPageMovableOps(zpdesc_page(zpdesc));
158}
159
160static inline void __zpdesc_set_zsmalloc(struct zpdesc *zpdesc)
161{
162	__SetPageZsmalloc(zpdesc_page(zpdesc));
163}
164
165static inline struct zone *zpdesc_zone(struct zpdesc *zpdesc)
166{
167	return page_zone(zpdesc_page(zpdesc));
168}
169
170static inline bool zpdesc_is_locked(struct zpdesc *zpdesc)
171{
172	return folio_test_locked(zpdesc_folio(zpdesc));
173}
174#endif
~/ Read-only file preview.