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