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