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