strategy(D2)strategy(D2)NAMEstrategy - perform block I/O
SYNOPSIS
#include <sys/types.h>
#include <sys/buf.h>
#include <sys/errno.h>
#include <sys/ddi.h>
int prefixstrategy(struct buf *bp);
Arguments
bp Pointer to the buffer header structure.
DESCRIPTION
The strategy routine is called by the kernel to read and write blocks of
data on the block device. strategy may also be called directly or
indirectly (via a call to the physiock(D3) function) to support the raw
character interface of a block device from read(D2), write(D2) or
ioctl(D2). The strategy routine's responsibility is to set up and
initiate the data transfer.
Return Values
Ignored. Errors are returned by using the bioerror(D3) function to mark
the buffer as being in error. On systems where the bioerror function is
not available, errors can be returned by setting the B_ERROR flag in the
b_flags field of the buf structure, and setting the error number in the
b_error field of the buf structure.
USAGE
This entry point is required in all block device drivers.
Generally, the first validation test performed by the strategy routine is
to see if the I/O is within the bounds of the device. If the starting
block number, given by bp->b_blkno, is less than 0 or greater than the
number of blocks on the device, the error number in the buffer header
should be set to ENXIO, and the B_ERROR flag should be set in bp-
>b_flags. If the bioerror routine is available, bioerror should be used
to set the buffer error number to ENXIO. Then, the buffer should be
marked done by calling biodone(D3), and the driver should return. If
bp->b_blkno is equal to the number of blocks on the device and the
operation is a write, indicated by the absence of the B_READ flag in bp-
>b_flags (!(bp->b_flags & B_READ)), then the same action should be taken.
However, if the operation is a read and bp->b_blkno is equal to the
number of blocks on the device, then the driver should set bp->b_resid
equal to bp->b_bcount, mark the buffer done by calling biodone, and
return. This will cause the read to return 0.
Once the I/O request has been validated, the strategy routine should
queue the request. If there is not already a transfer under way, the I/O
is started. Then the strategy routine returns. When the I/O is
complete, the driver will call biodone to free the buffer and notify
anyone who has called biowait(D3) to wait for the I/O to finish.
Page 1
strategy(D2)strategy(D2)
There are two kinds of I/O requests passed to strategy routines: normal
block I/O requests and paged-I/O requests. Normal block I/O requests are
identified by the absence of the B_PAGEIO flag or the presence of the
B_MAPPED in bp->b_flags. Here, the starting kernel virtual address of
the data transfer will be found in bp->b_un.b_addr. Paged-I/O requests
are identified by the presence of the B_PAGEIO flag in bp->b_flags. The
driver has several ways to perform a paged-I/O request.
If the driver wants to use virtual addresses, it can call bp_mapin(D3) to
get a virtually contiguous mapping for the pages. The physical address
can be obtained by calling kvtophys(D3X) for each page in the virtual
address range.
If the amount of data to be transferred is more than can be transferred,
the driver can transfer as much as possible (if it supports partial reads
and writes), and then use the bioerror function to set the buffer error
number to EIO. If the bioerror function is not available, the driver
should then set the B_ERROR flag, and set bp->b_resid equal to the number
of bytes not transferred (if all of the data were transferred, bp-
>b_resid should be set to 0).
Synchronization Constraints
The strategy entry point has the necessary context to sleep, but it
cannot assume it is called from the same context of the process that
initiated the I/O request. Furthermore, the process that initiated the
I/O might not even be in existence when the strategy routine is called.
REFERENCESbiodone(D3), bioerror(D3), biowait(D3), bp_mapin(D3), buf(D4),
devflag(D1), errnos(D5), kvtophys(D3X), physiock(D3), read(D2), write(D2)
Page 2