Line data Source code
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 : 30 : static inline void pagevec_init(struct pagevec *pvec) 31 : { 32 0 : pvec->nr = 0; 33 0 : pvec->percpu_pvec_drained = false; 34 : } 35 : 36 : static inline void pagevec_reinit(struct pagevec *pvec) 37 : { 38 0 : pvec->nr = 0; 39 : } 40 : 41 : static inline unsigned pagevec_count(struct pagevec *pvec) 42 : { 43 0 : return pvec->nr; 44 : } 45 : 46 : static inline unsigned pagevec_space(struct pagevec *pvec) 47 : { 48 : return PAGEVEC_SIZE - pvec->nr; 49 : } 50 : 51 : /* 52 : * Add a page to a pagevec. Returns the number of slots still available. 53 : */ 54 : static inline unsigned pagevec_add(struct pagevec *pvec, struct page *page) 55 : { 56 0 : pvec->pages[pvec->nr++] = page; 57 0 : return pagevec_space(pvec); 58 : } 59 : 60 : static inline void pagevec_release(struct pagevec *pvec) 61 : { 62 0 : if (pagevec_count(pvec)) 63 0 : __pagevec_release(pvec); 64 : } 65 : 66 : /** 67 : * struct folio_batch - A collection of folios. 68 : * 69 : * The folio_batch is used to amortise the cost of retrieving and 70 : * operating on a set of folios. The order of folios in the batch may be 71 : * significant (eg delete_from_page_cache_batch()). Some users of the 72 : * folio_batch store "exceptional" entries in it which can be removed 73 : * by calling folio_batch_remove_exceptionals(). 74 : */ 75 : struct folio_batch { 76 : unsigned char nr; 77 : bool percpu_pvec_drained; 78 : struct folio *folios[PAGEVEC_SIZE]; 79 : }; 80 : 81 : /* Layout must match pagevec */ 82 : static_assert(sizeof(struct pagevec) == sizeof(struct folio_batch)); 83 : static_assert(offsetof(struct pagevec, pages) == 84 : offsetof(struct folio_batch, folios)); 85 : 86 : /** 87 : * folio_batch_init() - Initialise a batch of folios 88 : * @fbatch: The folio batch. 89 : * 90 : * A freshly initialised folio_batch contains zero folios. 91 : */ 92 : static inline void folio_batch_init(struct folio_batch *fbatch) 93 : { 94 0 : fbatch->nr = 0; 95 0 : fbatch->percpu_pvec_drained = false; 96 : } 97 : 98 : static inline void folio_batch_reinit(struct folio_batch *fbatch) 99 : { 100 0 : fbatch->nr = 0; 101 : } 102 : 103 : static inline unsigned int folio_batch_count(struct folio_batch *fbatch) 104 : { 105 0 : return fbatch->nr; 106 : } 107 : 108 : static inline unsigned int fbatch_space(struct folio_batch *fbatch) 109 : { 110 : return PAGEVEC_SIZE - fbatch->nr; 111 : } 112 : 113 : /** 114 : * folio_batch_add() - Add a folio to a batch. 115 : * @fbatch: The folio batch. 116 : * @folio: The folio to add. 117 : * 118 : * The folio is added to the end of the batch. 119 : * The batch must have previously been initialised using folio_batch_init(). 120 : * 121 : * Return: The number of slots still available. 122 : */ 123 : static inline unsigned folio_batch_add(struct folio_batch *fbatch, 124 : struct folio *folio) 125 : { 126 0 : fbatch->folios[fbatch->nr++] = folio; 127 0 : return fbatch_space(fbatch); 128 : } 129 : 130 : static inline void folio_batch_release(struct folio_batch *fbatch) 131 : { 132 0 : pagevec_release((struct pagevec *)fbatch); 133 : } 134 : 135 : void folio_batch_remove_exceptionals(struct folio_batch *fbatch); 136 : #endif /* _LINUX_PAGEVEC_H */