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