strategy(D2DK) —
.IX \f4strategy\fP(D2DK)
NAME
strategy − perform block I/O
SYNOPSIS
#include <sys/types.h>
#include <sys/buf.h>
int prefixstrategy(struct buf ∗bp);
ARGUMENTS
bpPointer to the buffer header.
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 kernel function physiock(D3DK)), to support the raw character interface of a block device from read(D2DK), write(D2DK) or ioctl(D2DK). The strategy routine’s responsibility is to set up and initiate the data transfer.
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, bioerror(D3DK) should be used to set the buffer error number to ENXIO, the buffer should be marked done by calling biodone(D3DK), 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 will 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(D3DK) to wait for the I/O to finish.
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 in bp->b_flags. Here, the starting 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(D3DK) 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(D3DK) for each page in the virtual range. The size of a page can be determined by calling ptob(1). However, a more efficient way to use physical addresses is to use getnextpg(D3DK) and pptophys(D3DK) 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), use bioerror to set the buffer error number to EIO, 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.
NOTES
This entry point is required in all block drivers. 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.
RETURN VALUE
Ignored. Errors are returned by using bioerror to mark the buffer as being in error.
ERROR RETURN CODES
EAGAINTemporary resource allocation failure; try again later. Drivers can return this error when resource allocation fails, for example, kmem_alloc(D3DK) or allocb(D3DK).
EFAULTBad address. Drivers should return this error whenever a call to copyin(D3DK) or copyout(D3DK) fails.
EINTRInterrupted operation. Drivers can return this error whenever an interruptible operation is interrupted by receipt of an asynchronous signal.
EINVALInvalid argument. Drivers can return this error for operations that have invalid parameters specified.
EIOAn I/O error has occurred. Drivers can return this error when an input or output request has failed.
ENXIONo such device or address. Drivers can return this error when trying to open an invalid minor device, or when trying to perform I/O past the end of a device.
SEE ALSO
devflag(D1DK), read(D2DK), write(D2DK), biodone(D3DK), bioerror(D3DK), biowait(D3DK), bp_mapin(D3DK), getnextpg(D3DK), physiock(D3DK), pptophys(D3DK), buf(D4DK), errnos(D5DK)
DDI/DKI