buf(D4)

buf - block I/O data transfer structure

As shipped in IRIX 6.5.15. Last changed in IRIX 6.5.15.

NAME
     buf - block I/O data transfer structure

SYNOPSIS
     #include <sys/types.h>
     #include <sys/proc.h>
     #include <sys/buf.h>
     #include <sys/ddi.h>


DESCRIPTION
     The buf structure is the basic data structure for block I/O transfers.

USAGE
     Each block I/O transfer has an associated buffer header.  The header
     contains all the buffer control and status information.  For drivers, the
     buffer header pointer is the sole argument to a block driver strategy(D2)
     routine.  Do not depend on the size of the buf structure when writing a
     driver.

     It is important to note that a buffer header may be linked in multiple
     lists simultaneously.  Because of this, most of the members in the buffer
     header cannot be changed by the driver, even when the buffer header is in
     one of the drivers' work lists.

     Buffer headers may be used by the system to describe a portion of the
     kernel data space for I/O for block drivers.  Buffer headers are also
     used by the system for physical I/O for block drivers.  In this case, the
     buffer describes a portion of user data space that is locked into memory
     (see physiock(D3)).

     Block drivers often chain block requests so that overall throughput for
     the device is maximized.  The av_forw and the av_back members of the buf
     structure can serve as link pointers for chaining block requests.

   Structure Definitions
     The buf structure contains the following members:

     uint64_t        b_flags;        /* Buffer status */
     struct buf      *b_forw;        /* Kernel/driver list link */
     struct buf      *b_back;        /* Kernel/driver list link */
     struct buf      *av_forw;       /* Driver work list link */
     struct buf      *av_back;       /* Driver work list link */
     unsigned int    b_bcount;       /* # of bytes to transfer */
     union {
            caddr_t  b_addr;         /* Buffer's virtual address */
     } b_un;
     daddr_t         b_blkno;        /* Block number on device */
     unsigned int    b_resid;        /* # of bytes not transferred */
     clock_t         b_start;        /* Request start time */

     struct proc     *b_proc;        /* Process structure pointer */
     long            b_bufsize;      /* Size of allocated buffer */
     void            (*b_iodone)();  /* Function called by biodone */
     void            *b_iochain;     /* link pointer for iodone chain */
     dev_t           b_edev;         /* Expanded dev field */
     void            *b_private;     /* For driver's use in SVR4MP only*/

     The members of the buffer header available to test or set by a driver are
     described below:

     b_flags is a bitmask that stores the buffer status and tells the driver
     whether to read from or write to the device.  To avoid an error
     condition, the driver must never clear the b_flags member or modify its
     value, except by setting or clearing individual flag bits as described
     below.

     Valid flags are as follows:

          B_BUSY      The buffer is in use.  The driver may change this flag
                      only if it acquired the buffer with getrbuf(D3), and if
                      no I/O operation is in progress.

          B_DONE      The data transfer has completed.  The driver should not
                      change this flag.

          B_ERROR     The driver sets B_ERROR to indicate an error occurred
                      during an I/O transfer.  On systems where the
                      bioerror(D3) function is available, drivers should not
                      access this flag directly.

          B_PAGEIO    The buffer is being used in a paged I/O request.  If
                      B_PAGEIO is set, the b_pages field of the buffer header
                      points to a list of page structures sorted by block
                      location on the device.  Also, the b_un.b_addr field of
                      the buffer header is the offset into the first page of
                      the page list.  If B_PAGEIO is not set, the b_pages
                      field of the buffer header is not used and the
                      b_un.b_addr field of the buffer header contains the
                      starting virtual address of the I/O request (in user
                      address space if B_PHYS is set or kernel address space
                      otherwise).  The driver must not set or clear the
                      B_PAGEIO flag.

          B_PHYS      The buffer header is being used for physical (direct)
                      I/O to a user data area.  The b_un.b_addr member
                      contains the starting virtual address of the user data
                      area.  Note that B_PHYS and B_PAGEIO are never set
                      simultaneously and must not be changed by the driver.

          B_READ      Data are to be read from the peripheral device into main
                      memory.  The driver may change this flag only if it
                      acquired the buffer with getrbuf(D3), geteblk(D3), or
                      ngeteblk(D3), and if no I/O operation is in progress.

          B_WRITE     Data are to be transferred from main memory to the
                      peripheral device.  B_WRITE is a pseudo-flag that
                      occupies the same bit location as B_READ.  B_WRITE
                      cannot be directly tested; it is only detected as the
                      absence of B_READ (!(bp->b_flags&B_READ).)

     b_forw and b_back may only be used by the driver if the buffer was
     acquired by the driver with the getrbuf routine.  In that case, these
     members can be used to link the buffer into driver work lists.

     av_forw and av_back can be used by the driver to link the buffer into
     driver work lists.

     b_bcount specifies the number of bytes to be transferred for both paged
     and non-paged I/O requests.  The driver may change this member.

     b_un.b_addr is either the virtual address of the I/O request, or an
     offset into the first page of a page list depending on whether B_PAGEIO
     is set.  If it is set, the b_pages field of the buffer header points to a
     sorted list of page structures and b_un.b_addr is the offset into the
     first page.  If B_PAGEIO is not set, b_un.b_addr is the virtual address
     from which data are read or to which data are written.  It represents a
     user virtual address if B_PHYS is set, or a kernel virtual address
     otherwise.  The driver may change this member.

     b_blkno identifies which logical block on the device is to be accessed.
     The driver may have to convert this logical block number to a physical
     location such as a cylinder, track, and sector of a disk.  The driver may
     change this member only if it allocated the buffer via geteblk, ngeteblk,
     or getrbuf, and if no I/O operation is in progress.

     b_resid indicates the number of bytes not transferred.  The driver must
     set this member prior to calling biodone(D3).

     b_start holds the time the I/O request was started.  It is provided for
     the driver's use in calculating response time and is set by the driver.
     Its type, clock_t, is an integral type upon which direct integer
     calculations can be performed.  It represents clock ticks.

     b_proc contains the process structure address for the process requesting
     an unbuffered (direct) data transfer to or from a user data area (this
     member is set to NULL when the transfer is buffered).  The process table
     entry is used to perform proper virtual to physical address translation
     of the b_un.b_addr member.  The driver should not change this member.

     b_bufsize contains the size in bytes of the allocated buffer.  The driver
     may change this member only if it acquired the buffer with getrbuf, and
     if no I/O operation is in progress.

     (*b_iodone) identifies a specific driver routine to be called by the
     system when the I/O is complete.  If a routine is specified, the
     biodone(D3) routine does not return the buffer to the system.  The driver
     may change this member if no I/O operation is in progress.

     (*b_iochain) If b_iodone has been set by another driver layer, it is
     important to preserve its value and make sure it is called upon i/o
     completion.  b_iochain is proved for this purpose.  For example, a driver
     that wishes to use b_iodone should save the old value of b_iodone and
     b_iochain and write the address of these saved values into b_iochain and
     its completion routines address into b_iodone.  When the completion
     routine is called, it should restore both b_iodone and b_iochain and call
     biodone() with the buffer again.

     b_edev contains the external device number of the device.  The driver may
     change this member only if it allocated the buffer via geteblk, ngeteblk,
     or getrbuf, and if no I/O operation is in progress.

   Warnings
     Buffers are a shared resource within the kernel.  Drivers should only
     read or write the members listed in this section in accordance with the
     rules given above.  Drivers that attempt to use undocumented members of
     the buf structure risk corrupting data in the kernel and on the device.

     DDI/DKI-conforming drivers may only use buffer headers that have been
     allocated using geteblk, ngeteblk, or getrbuf, or have been passed to the
     driver strategy routine.

REFERENCES
     biodone(D3), bioerror(D3), biowait(D3), brelse(D3), clrbuf(D3),
     freerbuf(D3), geteblk(D3), geterror(D3), getrbuf(D3), iovec(D4),
     ngeteblk(D3), physiock(D3), strategy(D2), uio(D4), uiophysio(D3X).