Skip to content

Commit 28e8c5c

Browse files
dhowellsbrauner
authored andcommitted
netfs: Add folio_queue API documentation
Add API documentation for folio_queue. Signed-off-by: David Howells <[email protected]> Link: https://lore.kernel.org/r/[email protected] cc: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected] cc: [email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent 9fffa4e commit 28e8c5c

File tree

2 files changed

+380
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)