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