1*28e8c5c0SDavid Howells.. SPDX-License-Identifier: GPL-2.0+ 2*28e8c5c0SDavid Howells 3*28e8c5c0SDavid Howells=========== 4*28e8c5c0SDavid HowellsFolio Queue 5*28e8c5c0SDavid Howells=========== 6*28e8c5c0SDavid Howells 7*28e8c5c0SDavid Howells:Author: David Howells <[email protected]> 8*28e8c5c0SDavid Howells 9*28e8c5c0SDavid Howells.. Contents: 10*28e8c5c0SDavid Howells 11*28e8c5c0SDavid Howells * Overview 12*28e8c5c0SDavid Howells * Initialisation 13*28e8c5c0SDavid Howells * Adding and removing folios 14*28e8c5c0SDavid Howells * Querying information about a folio 15*28e8c5c0SDavid Howells * Querying information about a folio_queue 16*28e8c5c0SDavid Howells * Folio queue iteration 17*28e8c5c0SDavid Howells * Folio marks 18*28e8c5c0SDavid Howells * Lockless simultaneous production/consumption issues 19*28e8c5c0SDavid Howells 20*28e8c5c0SDavid Howells 21*28e8c5c0SDavid HowellsOverview 22*28e8c5c0SDavid Howells======== 23*28e8c5c0SDavid Howells 24*28e8c5c0SDavid HowellsThe folio_queue struct forms a single segment in a segmented list of folios 25*28e8c5c0SDavid Howellsthat can be used to form an I/O buffer. As such, the list can be iterated over 26*28e8c5c0SDavid Howellsusing the ITER_FOLIOQ iov_iter type. 27*28e8c5c0SDavid Howells 28*28e8c5c0SDavid HowellsThe publicly accessible members of the structure are:: 29*28e8c5c0SDavid Howells 30*28e8c5c0SDavid Howells struct folio_queue { 31*28e8c5c0SDavid Howells struct folio_queue *next; 32*28e8c5c0SDavid Howells struct folio_queue *prev; 33*28e8c5c0SDavid Howells ... 34*28e8c5c0SDavid Howells }; 35*28e8c5c0SDavid Howells 36*28e8c5c0SDavid HowellsA pair of pointers are provided, ``next`` and ``prev``, that point to the 37*28e8c5c0SDavid Howellssegments on either side of the segment being accessed. Whilst this is a 38*28e8c5c0SDavid Howellsdoubly-linked list, it is intentionally not a circular list; the outward 39*28e8c5c0SDavid Howellssibling pointers in terminal segments should be NULL. 40*28e8c5c0SDavid Howells 41*28e8c5c0SDavid HowellsEach segment in the list also stores: 42*28e8c5c0SDavid Howells 43*28e8c5c0SDavid Howells * an ordered sequence of folio pointers, 44*28e8c5c0SDavid Howells * the size of each folio and 45*28e8c5c0SDavid Howells * three 1-bit marks per folio, 46*28e8c5c0SDavid Howells 47*28e8c5c0SDavid Howellsbut hese should not be accessed directly as the underlying data structure may 48*28e8c5c0SDavid Howellschange, but rather the access functions outlined below should be used. 49*28e8c5c0SDavid Howells 50*28e8c5c0SDavid HowellsThe facility can be made accessible by:: 51*28e8c5c0SDavid Howells 52*28e8c5c0SDavid Howells #include <linux/folio_queue.h> 53*28e8c5c0SDavid Howells 54*28e8c5c0SDavid Howellsand to use the iterator:: 55*28e8c5c0SDavid Howells 56*28e8c5c0SDavid Howells #include <linux/uio.h> 57*28e8c5c0SDavid Howells 58*28e8c5c0SDavid Howells 59*28e8c5c0SDavid HowellsInitialisation 60*28e8c5c0SDavid Howells============== 61*28e8c5c0SDavid Howells 62*28e8c5c0SDavid HowellsA segment should be initialised by calling:: 63*28e8c5c0SDavid Howells 64*28e8c5c0SDavid Howells void folioq_init(struct folio_queue *folioq); 65*28e8c5c0SDavid Howells 66*28e8c5c0SDavid Howellswith a pointer to the segment to be initialised. Note that this will not 67*28e8c5c0SDavid Howellsnecessarily initialise all the folio pointers, so care must be taken to check 68*28e8c5c0SDavid Howellsthe number of folios added. 69*28e8c5c0SDavid Howells 70*28e8c5c0SDavid Howells 71*28e8c5c0SDavid HowellsAdding and removing folios 72*28e8c5c0SDavid Howells========================== 73*28e8c5c0SDavid Howells 74*28e8c5c0SDavid HowellsFolios can be set in the next unused slot in a segment struct by calling one 75*28e8c5c0SDavid Howellsof:: 76*28e8c5c0SDavid Howells 77*28e8c5c0SDavid Howells unsigned int folioq_append(struct folio_queue *folioq, 78*28e8c5c0SDavid Howells struct folio *folio); 79*28e8c5c0SDavid Howells 80*28e8c5c0SDavid Howells unsigned int folioq_append_mark(struct folio_queue *folioq, 81*28e8c5c0SDavid Howells struct folio *folio); 82*28e8c5c0SDavid Howells 83*28e8c5c0SDavid HowellsBoth functions update the stored folio count, store the folio and note its 84*28e8c5c0SDavid Howellssize. The second function also sets the first mark for the folio added. Both 85*28e8c5c0SDavid Howellsfunctions return the number of the slot used. [!] Note that no attempt is made 86*28e8c5c0SDavid Howellsto check that the capacity wasn't overrun and the list will not be extended 87*28e8c5c0SDavid Howellsautomatically. 88*28e8c5c0SDavid Howells 89*28e8c5c0SDavid HowellsA folio can be excised by calling:: 90*28e8c5c0SDavid Howells 91*28e8c5c0SDavid Howells void folioq_clear(struct folio_queue *folioq, unsigned int slot); 92*28e8c5c0SDavid Howells 93*28e8c5c0SDavid HowellsThis clears the slot in the array and also clears all the marks for that folio, 94*28e8c5c0SDavid Howellsbut doesn't change the folio count - so future accesses of that slot must check 95*28e8c5c0SDavid Howellsif the slot is occupied. 96*28e8c5c0SDavid Howells 97*28e8c5c0SDavid Howells 98*28e8c5c0SDavid HowellsQuerying information about a folio 99*28e8c5c0SDavid Howells================================== 100*28e8c5c0SDavid Howells 101*28e8c5c0SDavid HowellsInformation about the folio in a particular slot may be queried by the 102*28e8c5c0SDavid Howellsfollowing function:: 103*28e8c5c0SDavid Howells 104*28e8c5c0SDavid Howells struct folio *folioq_folio(const struct folio_queue *folioq, 105*28e8c5c0SDavid Howells unsigned int slot); 106*28e8c5c0SDavid Howells 107*28e8c5c0SDavid HowellsIf a folio has not yet been set in that slot, this may yield an undefined 108*28e8c5c0SDavid Howellspointer. The size of the folio in a slot may be queried with either of:: 109*28e8c5c0SDavid Howells 110*28e8c5c0SDavid Howells unsigned int folioq_folio_order(const struct folio_queue *folioq, 111*28e8c5c0SDavid Howells unsigned int slot); 112*28e8c5c0SDavid Howells 113*28e8c5c0SDavid Howells size_t folioq_folio_size(const struct folio_queue *folioq, 114*28e8c5c0SDavid Howells unsigned int slot); 115*28e8c5c0SDavid Howells 116*28e8c5c0SDavid HowellsThe first function returns the size as an order and the second as a number of 117*28e8c5c0SDavid Howellsbytes. 118*28e8c5c0SDavid Howells 119*28e8c5c0SDavid Howells 120*28e8c5c0SDavid HowellsQuerying information about a folio_queue 121*28e8c5c0SDavid Howells======================================== 122*28e8c5c0SDavid Howells 123*28e8c5c0SDavid HowellsInformation may be retrieved about a particular segment with the following 124*28e8c5c0SDavid Howellsfunctions:: 125*28e8c5c0SDavid Howells 126*28e8c5c0SDavid Howells unsigned int folioq_nr_slots(const struct folio_queue *folioq); 127*28e8c5c0SDavid Howells 128*28e8c5c0SDavid Howells unsigned int folioq_count(struct folio_queue *folioq); 129*28e8c5c0SDavid Howells 130*28e8c5c0SDavid Howells bool folioq_full(struct folio_queue *folioq); 131*28e8c5c0SDavid Howells 132*28e8c5c0SDavid HowellsThe first function returns the maximum capacity of a segment. It must not be 133*28e8c5c0SDavid Howellsassumed that this won't vary between segments. The second returns the number 134*28e8c5c0SDavid Howellsof folios added to a segments and the third is a shorthand to indicate if the 135*28e8c5c0SDavid Howellssegment has been filled to capacity. 136*28e8c5c0SDavid Howells 137*28e8c5c0SDavid HowellsNot that the count and fullness are not affected by clearing folios from the 138*28e8c5c0SDavid Howellssegment. These are more about indicating how many slots in the array have been 139*28e8c5c0SDavid Howellsinitialised, and it assumed that slots won't get reused, but rather the segment 140*28e8c5c0SDavid Howellswill get discarded as the queue is consumed. 141*28e8c5c0SDavid Howells 142*28e8c5c0SDavid Howells 143*28e8c5c0SDavid HowellsFolio marks 144*28e8c5c0SDavid Howells=========== 145*28e8c5c0SDavid Howells 146*28e8c5c0SDavid HowellsFolios within a queue can also have marks assigned to them. These marks can be 147*28e8c5c0SDavid Howellsused to note information such as if a folio needs folio_put() calling upon it. 148*28e8c5c0SDavid HowellsThere are three marks available to be set for each folio. 149*28e8c5c0SDavid Howells 150*28e8c5c0SDavid HowellsThe marks can be set by:: 151*28e8c5c0SDavid Howells 152*28e8c5c0SDavid Howells void folioq_mark(struct folio_queue *folioq, unsigned int slot); 153*28e8c5c0SDavid Howells void folioq_mark2(struct folio_queue *folioq, unsigned int slot); 154*28e8c5c0SDavid Howells void folioq_mark3(struct folio_queue *folioq, unsigned int slot); 155*28e8c5c0SDavid Howells 156*28e8c5c0SDavid HowellsCleared by:: 157*28e8c5c0SDavid Howells 158*28e8c5c0SDavid Howells void folioq_unmark(struct folio_queue *folioq, unsigned int slot); 159*28e8c5c0SDavid Howells void folioq_unmark2(struct folio_queue *folioq, unsigned int slot); 160*28e8c5c0SDavid Howells void folioq_unmark3(struct folio_queue *folioq, unsigned int slot); 161*28e8c5c0SDavid Howells 162*28e8c5c0SDavid HowellsAnd the marks can be queried by:: 163*28e8c5c0SDavid Howells 164*28e8c5c0SDavid Howells bool folioq_is_marked(const struct folio_queue *folioq, unsigned int slot); 165*28e8c5c0SDavid Howells bool folioq_is_marked2(const struct folio_queue *folioq, unsigned int slot); 166*28e8c5c0SDavid Howells bool folioq_is_marked3(const struct folio_queue *folioq, unsigned int slot); 167*28e8c5c0SDavid Howells 168*28e8c5c0SDavid HowellsThe marks can be used for any purpose and are not interpreted by this API. 169*28e8c5c0SDavid Howells 170*28e8c5c0SDavid Howells 171*28e8c5c0SDavid HowellsFolio queue iteration 172*28e8c5c0SDavid Howells===================== 173*28e8c5c0SDavid Howells 174*28e8c5c0SDavid HowellsA list of segments may be iterated over using the I/O iterator facility using 175*28e8c5c0SDavid Howellsan ``iov_iter`` iterator of ``ITER_FOLIOQ`` type. The iterator may be 176*28e8c5c0SDavid Howellsinitialised with:: 177*28e8c5c0SDavid Howells 178*28e8c5c0SDavid Howells void iov_iter_folio_queue(struct iov_iter *i, unsigned int direction, 179*28e8c5c0SDavid Howells const struct folio_queue *folioq, 180*28e8c5c0SDavid Howells unsigned int first_slot, unsigned int offset, 181*28e8c5c0SDavid Howells size_t count); 182*28e8c5c0SDavid Howells 183*28e8c5c0SDavid HowellsThis may be told to start at a particular segment, slot and offset within a 184*28e8c5c0SDavid Howellsqueue. The iov iterator functions will follow the next pointers when advancing 185*28e8c5c0SDavid Howellsand prev pointers when reverting when needed. 186*28e8c5c0SDavid Howells 187*28e8c5c0SDavid Howells 188*28e8c5c0SDavid HowellsLockless simultaneous production/consumption issues 189*28e8c5c0SDavid Howells=================================================== 190*28e8c5c0SDavid Howells 191*28e8c5c0SDavid HowellsIf properly managed, the list can be extended by the producer at the head end 192*28e8c5c0SDavid Howellsand shortened by the consumer at the tail end simultaneously without the need 193*28e8c5c0SDavid Howellsto take locks. The ITER_FOLIOQ iterator inserts appropriate barriers to aid 194*28e8c5c0SDavid Howellswith this. 195*28e8c5c0SDavid Howells 196*28e8c5c0SDavid HowellsCare must be taken when simultaneously producing and consuming a list. If the 197*28e8c5c0SDavid Howellslast segment is reached and the folios it refers to are entirely consumed by 198*28e8c5c0SDavid Howellsthe IOV iterators, an iov_iter struct will be left pointing to the last segment 199*28e8c5c0SDavid Howellswith a slot number equal to the capacity of that segment. The iterator will 200*28e8c5c0SDavid Howellstry to continue on from this if there's another segment available when it is 201*28e8c5c0SDavid Howellsused again, but care must be taken lest the segment got removed and freed by 202*28e8c5c0SDavid Howellsthe consumer before the iterator was advanced. 203*28e8c5c0SDavid Howells 204*28e8c5c0SDavid HowellsIt is recommended that the queue always contain at least one segment, even if 205*28e8c5c0SDavid Howellsthat segment has never been filled or is entirely spent. This prevents the 206*28e8c5c0SDavid Howellshead and tail pointers from collapsing. 207*28e8c5c0SDavid Howells 208*28e8c5c0SDavid Howells 209*28e8c5c0SDavid HowellsAPI Function Reference 210*28e8c5c0SDavid Howells====================== 211*28e8c5c0SDavid Howells 212*28e8c5c0SDavid Howells.. kernel-doc:: include/linux/folio_queue.h 213