xref: /freebsd/share/man/man9/sglist.9 (revision 3e8eb5c7f4909209c042403ddee340b2ee7003a5)
1.\"
2.\" Copyright (c) 2009 Hudson River Trading LLC
3.\" Written by: John H. Baldwin <jhb@FreeBSD.org>
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25.\" SUCH DAMAGE.
26.\"
27.\" $FreeBSD$
28.\"
29.Dd May 25, 2021
30.Dt SGLIST 9
31.Os
32.Sh NAME
33.Nm sglist ,
34.Nm sglist_alloc ,
35.Nm sglist_append ,
36.Nm sglist_append_bio ,
37.Nm sglist_append_mbuf ,
38.Nm sglist_append_mbuf_epg ,
39.Nm sglist_append_phys ,
40.Nm sglist_append_sglist ,
41.Nm sglist_append_single_mbuf ,
42.Nm sglist_append_uio ,
43.Nm sglist_append_user ,
44.Nm sglist_append_vmpages ,
45.Nm sglist_build ,
46.Nm sglist_clone ,
47.Nm sglist_consume_uio ,
48.Nm sglist_count ,
49.Nm sglist_count_mbuf_epg ,
50.Nm sglist_count_vmpages ,
51.Nm sglist_free ,
52.Nm sglist_hold ,
53.Nm sglist_init ,
54.Nm sglist_join ,
55.Nm sglist_length ,
56.Nm sglist_reset ,
57.Nm sglist_slice ,
58.Nm sglist_split
59.Nd manage a scatter/gather list of physical memory addresses
60.Sh SYNOPSIS
61.In sys/types.h
62.In sys/sglist.h
63.Ft struct sglist *
64.Fn sglist_alloc "int nsegs" "int mflags"
65.Ft int
66.Fn sglist_append "struct sglist *sg" "void *buf" "size_t len"
67.Ft int
68.Fn sglist_append_bio "struct sglist *sg" "struct bio *bp"
69.Ft int
70.Fn sglist_append_mbuf_epg "struct sglist *sg" "struct mbuf *m" "size_t offset" "size_t len"
71.Ft int
72.Fn sglist_append_mbuf "struct sglist *sg" "struct mbuf *m"
73.Ft int
74.Fn sglist_append_phys "struct sglist *sg" "vm_paddr_t paddr" "size_t len"
75.Ft int
76.Fn sglist_append_sglist "struct sglist *sg" "struct sglist *source" "size_t offset" "size_t len"
77.Ft int
78.Fn sglist_append_single_mbuf "struct sglist *sg" "struct mbuf *m"
79.Ft int
80.Fn sglist_append_uio "struct sglist *sg" "struct uio *uio"
81.Ft int
82.Fn sglist_append_user "struct sglist *sg" "void *buf" "size_t len" "struct thread *td"
83.Ft int
84.Fn sglist_append_vmpages "struct sglist *sg" "vm_page_t *m" "size_t pgoff" "size_t len"
85.Ft struct sglist *
86.Fn sglist_build "void *buf" "size_t len" "int mflags"
87.Ft struct sglist *
88.Fn sglist_clone "struct sglist *sg" "int mflags"
89.Ft int
90.Fn sglist_consume_uio "struct sglist *sg" "struct uio *uio" "size_t resid"
91.Ft int
92.Fn sglist_count "void *buf" "size_t len"
93.Ft int
94.Fn sglist_count_mbuf_epg "struct mbuf *m" "size_t offset" "size_t len"
95.Ft int
96.Fn sglist_count_vmpages "vm_page_t *m" "size_t pgoff" "size_t len"
97.Ft void
98.Fn sglist_free "struct sglist *sg"
99.Ft struct sglist *
100.Fn sglist_hold "struct sglist *sg"
101.Ft void
102.Fn sglist_init "struct sglist *sg" "int maxsegs" "struct sglist_seg *segs"
103.Ft int
104.Fn sglist_join "struct sglist *first" "struct sglist *second"
105.Ft size_t
106.Fn sglist_length "struct sglist *sg"
107.Ft void
108.Fn sglist_reset "struct sglist *sg"
109.Ft int
110.Fn sglist_slice "struct sglist *original" "struct sglist **slice" "size_t offset" "size_t length" "int mflags"
111.Ft int
112.Fn sglist_split "struct sglist *original" "struct sglist **head" "size_t length" "int mflags"
113.Sh DESCRIPTION
114The
115.Nm
116API manages physical address ranges.
117Each list contains one or more elements.
118Each element contains a starting physical address and a length.
119Scatter/gather lists are read-only while they are shared.
120If one wishes to alter an existing scatter/gather list and does not hold the
121sole reference to the list,
122then one should create a new list instead of modifying the existing list.
123.Pp
124Each scatter/gather list object contains a reference count.
125New lists are created with a single reference.
126New references are obtained by calling
127.Nm sglist_hold
128and are released by calling
129.Nm sglist_free .
130.Ss Allocating and Initializing Lists
131Each
132.Nm
133object consists of a header structure and a variable-length array of
134scatter/gather list elements.
135The
136.Nm sglist_alloc
137function allocates a new list that contains a header and
138.Fa nsegs
139scatter/gather list elements.
140The
141.Fa mflags
142argument can be set to either
143.Dv M_NOWAIT
144or
145.Dv M_WAITOK .
146.Pp
147The
148.Nm sglist_count
149function returns the number of scatter/gather list elements needed to describe
150the physical address ranges mapped by a single kernel virtual address range.
151The kernel virtual address range starts at
152.Fa buf
153and is
154.Fa len
155bytes long.
156.Pp
157The
158.Nm sglist_count_mbuf_epg
159function returns the number of scatter/gather list elements needed to describe
160the external multipage mbuf buffer
161.Fa m .
162The ranges start at an offset of
163.Fa offset
164relative to the start of the buffer and is
165.Fa len
166bytes long.
167.Pp
168The
169.Nm sglist_count_vmpages
170function returns the number of scatter/gather list elements needed to describe
171the physical address ranges of a buffer backed by an array of virtual memory
172pages
173.Fa m .
174The buffer starts at an offset of
175.Fa pgoff
176bytes relative to the first page and is
177.Fa len
178bytes long.
179.Pp
180The
181.Nm sglist_build
182function allocates a new scatter/gather list object that describes the physical
183address ranges mapped by a single kernel virtual address range.
184The kernel virtual address range starts at
185.Fa buf
186and is
187.Fa len
188bytes long.
189The
190.Fa mflags
191argument can be set to either
192.Dv M_NOWAIT
193or
194.Dv M_WAITOK .
195.Pp
196The
197.Nm sglist_clone
198function returns a copy of an existing scatter/gather list object
199.Fa sg .
200The
201.Fa mflags
202argument can be set to either
203.Dv M_NOWAIT
204or
205.Dv M_WAITOK .
206This can be used to obtain a private copy of a scatter/gather list before
207modifying it.
208.Pp
209The
210.Nm sglist_init
211function initializes a scatter/gather list header.
212The header is pointed to by
213.Fa sg
214and is initialized to manage an array of
215.Fa maxsegs
216scatter/gather list elements pointed to by
217.Fa segs .
218This can be used to initialize a scatter/gather list header whose storage
219is not provided by
220.Nm sglist_alloc .
221In that case, the caller should not call
222.Nm sglist_free
223to release its own reference and is responsible for ensuring all other
224references to the list are dropped before it releases the storage for
225.Fa sg
226and
227.Fa segs .
228.Ss Constructing Scatter/Gather Lists
229The
230.Nm
231API provides several routines for building a scatter/gather list to describe
232one or more objects.
233Specifically, the
234.Nm sglist_append
235family of routines can be used to append the physical address ranges described
236by an object to the end of a scatter/gather list.
237All of these routines return 0 on success or an error on failure.
238If a request to append an address range to a scatter/gather list fails,
239the scatter/gather list will remain unchanged.
240.Pp
241The
242.Nm sglist_append
243function appends the physical address ranges described by a single kernel
244virtual address range to the scatter/gather list
245.Fa sg .
246The kernel virtual address range starts at
247.Fa buf
248and is
249.Fa len
250bytes long.
251.Pp
252The
253.Nm sglist_append_bio
254function appends the physical address ranges described by a single bio
255.Fa bp
256to the scatter/gather list
257.Fa sg .
258.Pp
259The
260.Nm sglist_append_mbuf_epg
261function appends the physical address ranges described by the
262external multipage
263.Xr mbuf 9
264buffer
265.Fa ext_pgs
266to the scatter/gather list
267.Fa sg .
268The physical address ranges start at offset
269.Fa offset
270within
271.Fa ext_pgs
272and continue for
273.Fa len
274bytes.
275Note that unlike
276.Nm sglist_append_mbuf ,
277.Nm sglist_append_mbuf_epg
278only adds ranges for a single mbuf,
279not an entire mbuf chain.
280.Pp
281The
282.Nm sglist_append_mbuf
283function appends the physical address ranges described by an entire mbuf
284chain
285.Fa m
286to the scatter/gather list
287.Fa sg .
288.Pp
289The
290.Nm sglist_append_mbuf
291function appends the physical address ranges described by a single mbuf
292.Fa m
293to the scatter/gather list
294.Fa sg .
295.Pp
296The
297.Nm sglist_append_phys
298function appends a single physical address range to the scatter/gather list
299.Fa sg .
300The physical address range starts at
301.Fa paddr
302and is
303.Fa len
304bytes long.
305.Pp
306The
307.Nm sglist_append_sglist
308function appends physical address ranges described by the scatter/gather list
309.Fa source
310to the scatter/gather list
311.Fa sg .
312The physical address ranges start at offset
313.Fa offset
314within
315.Fa source
316and continue for
317.Fa len
318bytes.
319.Pp
320The
321.Nm sglist_append_uio
322function appends the physical address ranges described by a
323.Xr uio 9
324object to the scatter/gather list
325.Fa sg .
326Note that it is the caller's responsibility to ensure that the pages backing
327the I/O request are wired for the lifetime of
328.Fa sg .
329Note also that this routine does not modify
330.Fa uio .
331.Pp
332The
333.Nm sglist_append_user
334function appends the physical address ranges described by a single user
335virtual address range to the scatter/gather list
336.Fa sg .
337The user virtual address range is relative to the address space of the thread
338.Fa td .
339It starts at
340.Fa buf
341and is
342.Fa len
343bytes long.
344Note that it is the caller's responsibility to ensure that the pages backing
345the user buffer are wired for the lifetime of
346.Fa sg .
347.Pp
348The
349.Nm sglist_append_vmpages
350function appends the physical address ranges of a buffer backed by an array
351of virtual memory pages
352.Fa m .
353The buffer starts at an offset of
354.Fa pgoff
355bytes relative to the first page and is
356.Fa len
357bytes long.
358.Pp
359The
360.Nm sglist_consume_uio
361function is a variation of
362.Nm sglist_append_uio .
363As with
364.Nm sglist_append_uio ,
365it appends the physical address ranges described by
366.Fa uio
367to the scatter/gather list
368.Fa sg .
369Unlike
370.Nm sglist_append_uio ,
371however,
372.Nm sglist_consume_uio
373modifies the I/O request to indicate that the appended address ranges have
374been processed similar to calling
375.Xr uiomove 9 .
376This routine will only append ranges that describe up to
377.Fa resid
378total bytes in length.
379If the available segments in the scatter/gather list are exhausted before
380.Fa resid
381bytes are processed,
382then the
383.Fa uio
384structure will be updated to reflect the actual number of bytes processed,
385and
386.Nm sglist_consume_io
387will return zero to indicate success.
388In effect, this function will perform partial reads or writes.
389The caller can compare the
390.Fa uio_resid
391member of
392.Fa uio
393before and after calling
394.Nm sglist_consume_uio
395to determine the actual number of bytes processed.
396.Ss Manipulating Scatter/Gather Lists
397The
398.Nm sglist_join
399function appends physical address ranges from the scatter/gather list
400.Fa second
401onto
402.Fa first
403and then resets
404.Fa second
405to an empty list.
406It returns zero on success or an error on failure.
407.Pp
408The
409.Nm sglist_split
410function splits an existing scatter/gather list into two lists.
411The first
412.Fa length
413bytes described by the list
414.Fa original
415are moved to a new list
416.Fa *head .
417If
418.Fa original
419describes a total address range that is smaller than
420.Fa length
421bytes,
422then all of the address ranges will be moved to the new list at
423.Fa *head
424and
425.Fa original
426will be an empty list.
427The caller may supply an existing scatter/gather list in
428.Fa *head .
429If so, the list must be empty.
430Otherwise, the caller may set
431.Fa *head
432to
433.Dv NULL
434in which case a new scatter/gather list will be allocated.
435In that case,
436.Fa mflags
437may be set to either
438.Dv M_NOWAIT
439or
440.Dv M_WAITOK .
441Note that since the
442.Fa original
443list is modified by this call, it must be a private list with no other
444references.
445The
446.Nm sglist_split
447function returns zero on success or an error on failure.
448.Pp
449The
450.Nm sglist_slice
451function generates a new scatter/gather list from a sub-range of an existing
452scatter/gather list
453.Fa original .
454The sub-range to extract is specified by the
455.Fa offset
456and
457.Fa length
458parameters.
459The new scatter/gather list is stored in
460.Fa *slice .
461As with
462.Fa head
463for
464.Nm sglist_join ,
465the caller may either provide an empty scatter/gather list,
466or it may set
467.Fa *slice
468to
469.Dv NULL
470in which case
471.Nm sglist_slice
472will allocate a new list subject to
473.Fa mflags .
474Unlike
475.Nm sglist_split ,
476.Nm sglist_slice
477does not modify
478.Fa original
479and does not require it to be a private list.
480The
481.Nm sglist_split
482function returns zero on success or an error on failure.
483.Ss Miscellaneous Routines
484The
485.Nm sglist_reset
486function clears the scatter/gather list
487.Fa sg
488so that it no longer maps any address ranges.
489This can allow reuse of a single scatter/gather list object for multiple
490requests.
491.Pp
492The
493.Nm sglist_length
494function returns the total length of the physical address ranges described
495by the scatter/gather list
496.Fa sg .
497.Sh RETURN VALUES
498The
499.Nm sglist_alloc ,
500.Nm sglist_build ,
501and
502.Nm sglist_clone
503functions return a new scatter/gather list on success or
504.Dv NULL
505on failure.
506.Pp
507The
508.Nm sglist_append
509family of functions and the
510.Nm sglist_consume_uio ,
511.Nm sglist_join ,
512.Nm sglist_slice ,
513and
514.Nm sglist_split
515functions return zero on success or an error on failure.
516.Pp
517The
518.Nm sglist_count
519family of
520functions return a count of scatter/gather list elements.
521.Pp
522The
523.Nm sglist_length
524function returns a count of address space described by a scatter/gather list
525in bytes.
526.Sh ERRORS
527The
528.Nm sglist_append
529functions return the following errors on failure:
530.Bl -tag -width Er
531.It Bq Er EINVAL
532The scatter/gather list has zero segments.
533.It Bq Er EFBIG
534There are not enough available segments in the scatter/gather list to append
535the specified physical address ranges.
536.El
537.Pp
538The
539.Nm sglist_consume_uio
540function returns the following error on failure:
541.Bl -tag -width Er
542.It Bq Er EINVAL
543The scatter/gather list has zero segments.
544.El
545.Pp
546The
547.Nm sglist_join
548function returns the following error on failure:
549.Bl -tag -width Er
550.It Bq Er EFBIG
551There are not enough available segments in the scatter/gather list
552.Fa first
553to append the physical address ranges from
554.Fa second .
555.El
556.Pp
557The
558.Nm sglist_slice
559function returns the following errors on failure:
560.Bl -tag -width Er
561.It Bq Er EINVAL
562The
563.Fa original
564scatter/gather list does not describe enough address space to cover the
565requested sub-range.
566.It Bq Er EINVAL
567The caller-supplied scatter/gather list in
568.Fa *slice
569is not empty.
570.It Bq Er ENOMEM
571An attempt to allocate a new scatter/gather list with
572.Dv M_NOWAIT
573set in
574.Fa mflags
575failed.
576.It Bq Er EFBIG
577There are not enough available segments in the caller-supplied scatter/gather
578list in
579.Fa *slice
580to describe the requested physical address ranges.
581.El
582.Pp
583The
584.Nm sglist_split
585function returns the following errors on failure:
586.Bl -tag -width Er
587.It Bq Er EDOOFUS
588The
589.Fa original
590scatter/gather list has more than one reference.
591.It Bq Er EINVAL
592The caller-supplied scatter/gather list in
593.Fa *head
594is not empty.
595.It Bq Er ENOMEM
596An attempt to allocate a new scatter/gather list with
597.Dv M_NOWAIT
598set in
599.Fa mflags
600failed.
601.It Bq Er EFBIG
602There are not enough available segments in the caller-supplied scatter/gather
603list in
604.Fa *head
605to describe the requested physical address ranges.
606.El
607.Sh SEE ALSO
608.Xr g_bio 9 ,
609.Xr malloc 9 ,
610.Xr mbuf 9 ,
611.Xr uio 9
612.Sh HISTORY
613This API was first introduced in
614.Fx 8.0 .
615