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