Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 LT |
2 | /* |
3 | * include/linux/pagevec.h | |
4 | * | |
5 | * In many places it is efficient to batch an operation up against multiple | |
6 | * pages. A pagevec is a multipage container which is used for that. | |
7 | */ | |
8 | ||
78854014 DH |
9 | #ifndef _LINUX_PAGEVEC_H |
10 | #define _LINUX_PAGEVEC_H | |
11 | ||
10bbd235 MW |
12 | #include <linux/xarray.h> |
13 | ||
146500e9 MW |
14 | /* 15 pointers + header align the pagevec structure to a power of two */ |
15 | #define PAGEVEC_SIZE 15 | |
1da177e4 LT |
16 | |
17 | struct page; | |
10331795 | 18 | struct folio; |
1da177e4 LT |
19 | struct address_space; |
20 | ||
10331795 | 21 | /* Layout must match folio_batch */ |
1da177e4 | 22 | struct pagevec { |
146500e9 | 23 | unsigned char nr; |
7f0b5fb9 | 24 | bool percpu_pvec_drained; |
1da177e4 LT |
25 | struct page *pages[PAGEVEC_SIZE]; |
26 | }; | |
27 | ||
28 | void __pagevec_release(struct pagevec *pvec); | |
a0b8cab3 | 29 | void __pagevec_lru_add(struct pagevec *pvec); |
b947cee4 JK |
30 | unsigned pagevec_lookup_range(struct pagevec *pvec, |
31 | struct address_space *mapping, | |
397162ff | 32 | pgoff_t *start, pgoff_t end); |
b947cee4 JK |
33 | static inline unsigned pagevec_lookup(struct pagevec *pvec, |
34 | struct address_space *mapping, | |
397162ff | 35 | pgoff_t *start) |
b947cee4 | 36 | { |
397162ff | 37 | return pagevec_lookup_range(pvec, mapping, start, (pgoff_t)-1); |
b947cee4 JK |
38 | } |
39 | ||
72b045ae JK |
40 | unsigned pagevec_lookup_range_tag(struct pagevec *pvec, |
41 | struct address_space *mapping, pgoff_t *index, pgoff_t end, | |
10bbd235 | 42 | xa_mark_t tag); |
72b045ae | 43 | static inline unsigned pagevec_lookup_tag(struct pagevec *pvec, |
10bbd235 | 44 | struct address_space *mapping, pgoff_t *index, xa_mark_t tag) |
72b045ae | 45 | { |
67fd707f | 46 | return pagevec_lookup_range_tag(pvec, mapping, index, (pgoff_t)-1, tag); |
72b045ae | 47 | } |
1da177e4 | 48 | |
86679820 | 49 | static inline void pagevec_init(struct pagevec *pvec) |
1da177e4 LT |
50 | { |
51 | pvec->nr = 0; | |
7f0b5fb9 | 52 | pvec->percpu_pvec_drained = false; |
1da177e4 LT |
53 | } |
54 | ||
55 | static inline void pagevec_reinit(struct pagevec *pvec) | |
56 | { | |
57 | pvec->nr = 0; | |
58 | } | |
59 | ||
60 | static inline unsigned pagevec_count(struct pagevec *pvec) | |
61 | { | |
62 | return pvec->nr; | |
63 | } | |
64 | ||
65 | static inline unsigned pagevec_space(struct pagevec *pvec) | |
66 | { | |
67 | return PAGEVEC_SIZE - pvec->nr; | |
68 | } | |
69 | ||
70 | /* | |
71 | * Add a page to a pagevec. Returns the number of slots still available. | |
72 | */ | |
73 | static inline unsigned pagevec_add(struct pagevec *pvec, struct page *page) | |
74 | { | |
75 | pvec->pages[pvec->nr++] = page; | |
76 | return pagevec_space(pvec); | |
77 | } | |
78 | ||
1da177e4 LT |
79 | static inline void pagevec_release(struct pagevec *pvec) |
80 | { | |
81 | if (pagevec_count(pvec)) | |
82 | __pagevec_release(pvec); | |
83 | } | |
84 | ||
10331795 MWO |
85 | /** |
86 | * struct folio_batch - A collection of folios. | |
87 | * | |
88 | * The folio_batch is used to amortise the cost of retrieving and | |
89 | * operating on a set of folios. The order of folios in the batch may be | |
90 | * significant (eg delete_from_page_cache_batch()). Some users of the | |
91 | * folio_batch store "exceptional" entries in it which can be removed | |
92 | * by calling folio_batch_remove_exceptionals(). | |
93 | */ | |
94 | struct folio_batch { | |
95 | unsigned char nr; | |
96 | bool percpu_pvec_drained; | |
97 | struct folio *folios[PAGEVEC_SIZE]; | |
98 | }; | |
99 | ||
100 | /* Layout must match pagevec */ | |
101 | static_assert(sizeof(struct pagevec) == sizeof(struct folio_batch)); | |
102 | static_assert(offsetof(struct pagevec, pages) == | |
103 | offsetof(struct folio_batch, folios)); | |
104 | ||
105 | /** | |
106 | * folio_batch_init() - Initialise a batch of folios | |
107 | * @fbatch: The folio batch. | |
108 | * | |
109 | * A freshly initialised folio_batch contains zero folios. | |
110 | */ | |
111 | static inline void folio_batch_init(struct folio_batch *fbatch) | |
112 | { | |
113 | fbatch->nr = 0; | |
6840f909 | 114 | fbatch->percpu_pvec_drained = false; |
10331795 MWO |
115 | } |
116 | ||
117 | static inline unsigned int folio_batch_count(struct folio_batch *fbatch) | |
118 | { | |
119 | return fbatch->nr; | |
120 | } | |
121 | ||
122 | static inline unsigned int fbatch_space(struct folio_batch *fbatch) | |
123 | { | |
124 | return PAGEVEC_SIZE - fbatch->nr; | |
125 | } | |
126 | ||
127 | /** | |
128 | * folio_batch_add() - Add a folio to a batch. | |
129 | * @fbatch: The folio batch. | |
130 | * @folio: The folio to add. | |
131 | * | |
132 | * The folio is added to the end of the batch. | |
133 | * The batch must have previously been initialised using folio_batch_init(). | |
134 | * | |
135 | * Return: The number of slots still available. | |
136 | */ | |
137 | static inline unsigned folio_batch_add(struct folio_batch *fbatch, | |
138 | struct folio *folio) | |
139 | { | |
140 | fbatch->folios[fbatch->nr++] = folio; | |
141 | return fbatch_space(fbatch); | |
142 | } | |
143 | ||
144 | static inline void folio_batch_release(struct folio_batch *fbatch) | |
145 | { | |
146 | pagevec_release((struct pagevec *)fbatch); | |
147 | } | |
148 | ||
1613fac9 | 149 | void folio_batch_remove_exceptionals(struct folio_batch *fbatch); |
78854014 | 150 | #endif /* _LINUX_PAGEVEC_H */ |