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