1 /* Public domain. */
2
3 #ifndef _LINUXKPI_LINUX_PAGEVEC_H_
4 #define _LINUXKPI_LINUX_PAGEVEC_H_
5
6 #include <sys/types.h>
7 #include <sys/systm.h>
8 #include <sys/errno.h>
9
10 #include <linux/pagemap.h>
11
12 #define PAGEVEC_SIZE 15
13
14 struct pagevec {
15 uint8_t nr;
16 struct page *pages[PAGEVEC_SIZE];
17 };
18
19 static inline unsigned int
pagevec_space(struct pagevec * pvec)20 pagevec_space(struct pagevec *pvec)
21 {
22 return PAGEVEC_SIZE - pvec->nr;
23 }
24
25 static inline void
pagevec_init(struct pagevec * pvec)26 pagevec_init(struct pagevec *pvec)
27 {
28 pvec->nr = 0;
29 }
30
31 static inline void
pagevec_reinit(struct pagevec * pvec)32 pagevec_reinit(struct pagevec *pvec)
33 {
34 pvec->nr = 0;
35 }
36
37 static inline unsigned int
pagevec_count(struct pagevec * pvec)38 pagevec_count(struct pagevec *pvec)
39 {
40 return pvec->nr;
41 }
42
43 static inline unsigned int
pagevec_add(struct pagevec * pvec,struct page * page)44 pagevec_add(struct pagevec *pvec, struct page *page)
45 {
46 pvec->pages[pvec->nr++] = page;
47 return PAGEVEC_SIZE - pvec->nr;
48 }
49
50 static inline void
__pagevec_release(struct pagevec * pvec)51 __pagevec_release(struct pagevec *pvec)
52 {
53 release_pages(pvec->pages, pagevec_count(pvec));
54 pagevec_reinit(pvec);
55 }
56
57 static inline void
pagevec_release(struct pagevec * pvec)58 pagevec_release(struct pagevec *pvec)
59 {
60 if (pagevec_count(pvec))
61 __pagevec_release(pvec);
62 }
63
64 static inline void
check_move_unevictable_pages(struct pagevec * pvec)65 check_move_unevictable_pages(struct pagevec *pvec)
66 {
67 }
68
69 /*
70 * struct folio
71 *
72 * On Linux, `struct folio` replaces `struct page`. To manage a list of folios,
73 * there is `struct folio_batch` on top of this, which replaces `struct
74 * pagevec` above.
75 *
76 * Here is the original description when `struct folio` was added to the Linux
77 * kernel:
78 * "A struct folio is a new abstraction to replace the venerable struct page.
79 * A function which takes a struct folio argument declares that it will
80 * operate on the entire (possibly compound) page, not just PAGE_SIZE bytes.
81 * In return, the caller guarantees that the pointer it is passing does not
82 * point to a tail page. No change to generated code."
83 */
84
85 struct folio;
86
87 struct folio_batch {
88 uint8_t nr;
89 struct folio *folios[PAGEVEC_SIZE];
90 };
91
92 static inline void
folio_batch_init(struct folio_batch * fbatch)93 folio_batch_init(struct folio_batch *fbatch)
94 {
95 fbatch->nr = 0;
96 }
97
98 static inline void
folio_batch_reinit(struct folio_batch * fbatch)99 folio_batch_reinit(struct folio_batch *fbatch)
100 {
101 fbatch->nr = 0;
102 }
103
104 static inline unsigned int
folio_batch_count(struct folio_batch * fbatch)105 folio_batch_count(struct folio_batch *fbatch)
106 {
107 return (fbatch->nr);
108 }
109
110 static inline unsigned int
folio_batch_space(struct folio_batch * fbatch)111 folio_batch_space(struct folio_batch *fbatch)
112 {
113 return (PAGEVEC_SIZE - fbatch->nr);
114 }
115
116 static inline unsigned int
folio_batch_add(struct folio_batch * fbatch,struct folio * folio)117 folio_batch_add(struct folio_batch *fbatch, struct folio *folio)
118 {
119 KASSERT(
120 fbatch->nr < PAGEVEC_SIZE,
121 ("struct folio_batch %p is full", fbatch));
122
123 fbatch->folios[fbatch->nr++] = folio;
124
125 return (folio_batch_space(fbatch));
126 }
127
128 void __folio_batch_release(struct folio_batch *fbatch);
129
130 static inline void
folio_batch_release(struct folio_batch * fbatch)131 folio_batch_release(struct folio_batch *fbatch)
132 {
133 if (folio_batch_count(fbatch))
134 __folio_batch_release(fbatch);
135 }
136
137 #endif /* _LINUXKPI_LINUX_PAGEVEC_H_ */
138