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