strategy(D2) strategy(D2)
NAME
strategy - 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
Copyright 1994 Novell, Inc. Page 1
strategy(D2) strategy(D2)
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.
There are two kinds of I/O requests passed to strategy
routines by the kernel: 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 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. These
will not occur unless the driver has set the D_NOBRKUP flag
[see devflag(D1)]. 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. If the driver wants to use physical addresses, it can
also use bp_mapin, but only transfer one page at a time. The
physical address can be obtained by calling vtop(D3) for each
page in the virtual range. The size of a page can be
determined by calling ptob(D3). However, a more efficient way
to use physical addresses is to use getnextpg(D3) and
pptophys(D3) (if these routines are available) for each page
in the page list.
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).
Copyright 1994 Novell, Inc. Page 2
strategy(D2) strategy(D2)
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.
REFERENCES
biodone(D3), bioerror(D3), biowait(D3), bp_mapin(D3), buf(D4),
devflag(D1), errnos(D5), getnextpg(D3), physiock(D3),
pptophys(D3), read(D2), write(D2)
NOTICES
Portability
All processors
Applicability
ddi: 1, 2, 3, 4, 5, 5mp, 6, 6mp, 7, 7mp
Copyright 1994 Novell, Inc. Page 3