buf(D4)buf(D4)NAMEbuf - 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 */
Page 1
buf(D4)buf(D4)
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
Page 2
buf(D4)buf(D4)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.
Page 3
buf(D4)buf(D4)
(*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.
REFERENCESbiodone(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).
Page 4