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