121 lines
4.6 KiB
Plaintext
121 lines
4.6 KiB
Plaintext
.if n .pH ddi.rm/d2/gen/strategy @(#)strategy 43.15 of 11/25/92
|
|
.\" Copyright 1992, 1991 UNIX System Laboratories, Inc.
|
|
.TH strategy D2
|
|
.IX "\f4strategy\fP(D2)"
|
|
.SH NAME
|
|
\f4strategy\fP \- perform block I/O
|
|
.SH SYNOPSIS
|
|
.nf
|
|
.na
|
|
.ft 4
|
|
#include <sys/types.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/ddi.h>
|
|
.sp 0.4
|
|
int \f2prefix\fPstrategy(struct buf *\f2bp\fP);
|
|
.ft 1
|
|
.ad
|
|
.fi
|
|
.SS Arguments
|
|
.RS 0
|
|
.IP "\f2bp\fP" 10n
|
|
Pointer to the buffer header structure.
|
|
.RE
|
|
.SH DESCRIPTION
|
|
.P
|
|
The \f4strategy\fP routine is called by the kernel to read and
|
|
write blocks of data on the block device.
|
|
\f4strategy\fP may also be called directly or indirectly
|
|
(via a call to the \f4physiock\fP(D3) function)
|
|
to support the raw character interface of a block device
|
|
from \f4read\fP(D2), \f4write\fP(D2) or \f4ioctl\fP(D2).
|
|
The \f4strategy\fP routine's responsibility is
|
|
to set up and initiate the data transfer.
|
|
.SS "Return Values"
|
|
Ignored.
|
|
Errors are returned by using the \f4bioerror\fP(D3) function
|
|
to mark the buffer as being in error.
|
|
On systems where the \f4bioerror\fP function is not available,
|
|
errors can be returned by setting the \f4B_ERROR\fP flag
|
|
in the \f4b_flags\fP field of the \f4buf\fP structure,
|
|
and setting the error number in the \f4b_error\fP field
|
|
of the \f4buf\fP structure.
|
|
.SH USAGE
|
|
This entry point is required in all block device drivers.
|
|
.P
|
|
Generally, the first validation test performed by the \f4strategy\fP
|
|
routine is to see if the I/O is within the bounds of the device.
|
|
If the starting block number, given by \f4bp->b_blkno\fP,
|
|
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 \f4ENXIO\fP,
|
|
and the \f4B_ERROR\fP flag should be set in \f4bp->b_flags\fP.
|
|
If the \f4bioerror\fP routine is available,
|
|
\f4bioerror\fP should be used to set the buffer error number to
|
|
\f4ENXIO\fP.
|
|
Then, the buffer should be marked done by calling \f4biodone\fP(D3),
|
|
and the driver should return.
|
|
If \f4bp->b_blkno\fP is equal to the number of blocks on the device and
|
|
the operation is a write, indicated by the absence of the \f4B_READ\fP flag
|
|
in \f4bp->b_flags\fP (\f4!(bp->b_flags & B_READ)\fP), then the same action
|
|
should be taken.
|
|
However, if the operation is a read and
|
|
\f4bp->b_blkno\fP is equal to the number of blocks on the device,
|
|
then the driver should set \f4bp->b_resid\fP equal to \f4bp->b_bcount\fP,
|
|
mark the buffer done by calling \f4biodone\fP, and return.
|
|
This will cause the read to return 0.
|
|
.P
|
|
Once the I/O request has been validated,
|
|
the \f4strategy\fP routine should queue the request.
|
|
If there is not already a transfer under way, the I/O is
|
|
started.
|
|
Then the \f4strategy\fP routine returns.
|
|
When the I/O is complete,
|
|
the driver will call \f4biodone\fP to free the buffer and notify anyone who
|
|
has called \f4biowait\fP(D3) to wait for the I/O to finish.
|
|
.P
|
|
There are two kinds of I/O requests passed to \f4strategy\fP routines:
|
|
normal block I/O requests and paged-I/O requests.
|
|
Normal block I/O requests are identified
|
|
by the absence of the \f4B_PAGEIO\fP flag or the presence of the
|
|
\f4B_MAPPED\fP in \f4bp->b_flags\fP.
|
|
Here, the starting kernel virtual address of the data transfer
|
|
will be found in \f4bp->b_un.b_addr\fP.
|
|
Paged-I/O requests are identified by the presence
|
|
of the \f4B_PAGEIO\fP flag in \f4bp->b_flags\fP.
|
|
The driver has several ways to perform a paged-I/O request.
|
|
.P
|
|
If the driver wants to use virtual addresses, it can call \f4bp_mapin\fP(D3) to get
|
|
a virtually contiguous mapping for the pages.
|
|
The physical address can be obtained by calling \f4kvtophys\fP(D3X) for each page
|
|
in the virtual address range.
|
|
.P
|
|
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 \f4bioerror\fP function to set the buffer error number to EIO.
|
|
If the \f4bioerror\fP function is not available,
|
|
the driver should then set the \f4B_ERROR\fP flag,
|
|
and set \f4bp->b_resid\fP equal to the number of bytes not transferred
|
|
(if all of the data were transferred, \f4bp->b_resid\fP should be set to 0).
|
|
.SS "Synchronization Constraints"
|
|
The \f4strategy\fP 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 \f4strategy\fP routine
|
|
is called.
|
|
.SH REFERENCES
|
|
\f4biodone\fP(D3),
|
|
\f4bioerror\fP(D3),
|
|
\f4biowait\fP(D3),
|
|
\f4bp_mapin\fP(D3),
|
|
\f4buf\fP(D4),
|
|
\f4devflag\fP(D1),
|
|
\f4errnos\fP(D5),
|
|
\f4kvtophys\fP(D3X),
|
|
\f4physiock\fP(D3),
|
|
\f4read\fP(D2),
|
|
\f4write\fP(D2)
|
|
.ad
|