1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * include/linux/pagevec.h |
4 | * |
5 | * In many places it is efficient to batch an operation up against multiple |
6 | * folios. A folio_batch is a container which is used for that. |
7 | */ |
8 | |
9 | #ifndef _LINUX_PAGEVEC_H |
10 | #define _LINUX_PAGEVEC_H |
11 | |
12 | #include <linux/types.h> |
13 | |
14 | /* 31 pointers + header align the folio_batch structure to a power of two */ |
15 | #define PAGEVEC_SIZE 31 |
16 | |
17 | struct folio; |
18 | |
19 | /** |
20 | * struct folio_batch - A collection of folios. |
21 | * |
22 | * The folio_batch is used to amortise the cost of retrieving and |
23 | * operating on a set of folios. The order of folios in the batch may be |
24 | * significant (eg delete_from_page_cache_batch()). Some users of the |
25 | * folio_batch store "exceptional" entries in it which can be removed |
26 | * by calling folio_batch_remove_exceptionals(). |
27 | */ |
28 | struct folio_batch { |
29 | unsigned char nr; |
30 | unsigned char i; |
31 | bool percpu_pvec_drained; |
32 | struct folio *folios[PAGEVEC_SIZE]; |
33 | }; |
34 | |
35 | /** |
36 | * folio_batch_init() - Initialise a batch of folios |
37 | * @fbatch: The folio batch. |
38 | * |
39 | * A freshly initialised folio_batch contains zero folios. |
40 | */ |
41 | static inline void folio_batch_init(struct folio_batch *fbatch) |
42 | { |
43 | fbatch->nr = 0; |
44 | fbatch->i = 0; |
45 | fbatch->percpu_pvec_drained = false; |
46 | } |
47 | |
48 | static inline void folio_batch_reinit(struct folio_batch *fbatch) |
49 | { |
50 | fbatch->nr = 0; |
51 | fbatch->i = 0; |
52 | } |
53 | |
54 | static inline unsigned int folio_batch_count(struct folio_batch *fbatch) |
55 | { |
56 | return fbatch->nr; |
57 | } |
58 | |
59 | static inline unsigned int folio_batch_space(struct folio_batch *fbatch) |
60 | { |
61 | return PAGEVEC_SIZE - fbatch->nr; |
62 | } |
63 | |
64 | /** |
65 | * folio_batch_add() - Add a folio to a batch. |
66 | * @fbatch: The folio batch. |
67 | * @folio: The folio to add. |
68 | * |
69 | * The folio is added to the end of the batch. |
70 | * The batch must have previously been initialised using folio_batch_init(). |
71 | * |
72 | * Return: The number of slots still available. |
73 | */ |
74 | static inline unsigned folio_batch_add(struct folio_batch *fbatch, |
75 | struct folio *folio) |
76 | { |
77 | fbatch->folios[fbatch->nr++] = folio; |
78 | return folio_batch_space(fbatch); |
79 | } |
80 | |
81 | /** |
82 | * folio_batch_next - Return the next folio to process. |
83 | * @fbatch: The folio batch being processed. |
84 | * |
85 | * Use this function to implement a queue of folios. |
86 | * |
87 | * Return: The next folio in the queue, or NULL if the queue is empty. |
88 | */ |
89 | static inline struct folio *folio_batch_next(struct folio_batch *fbatch) |
90 | { |
91 | if (fbatch->i == fbatch->nr) |
92 | return NULL; |
93 | return fbatch->folios[fbatch->i++]; |
94 | } |
95 | |
96 | void __folio_batch_release(struct folio_batch *pvec); |
97 | |
98 | static inline void folio_batch_release(struct folio_batch *fbatch) |
99 | { |
100 | if (folio_batch_count(fbatch)) |
101 | __folio_batch_release(pvec: fbatch); |
102 | } |
103 | |
104 | void folio_batch_remove_exceptionals(struct folio_batch *fbatch); |
105 | #endif /* _LINUX_PAGEVEC_H */ |
106 | |