zpdesc.h 4.9 KB

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