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