Kernel Functions for Drivers bioclone(9F)
NAME
bioclone - clone another buffer
SYNOPSIS
#include #include
struct buf *bioclone(struct buf *bp, offt off, sizet len, devt dev,
daddrt blkno, int (*iodone) (struct buf *), struct buf *bpmem,
int sleepflag);
INTERFACE LEVEL
Solaris DI specific (Solaris DI).
PARAMETERS
bp Pointer to the buf(9S) structure describing the
original I/O request.
off Offset within original I/O request where new
I/O request should start.
len Length of the I/O request.
dev Device number.
blkno Block number on device.
iodone Specific biodone(9F) routine.
bpmem Pointer to a buffer structure to be filled in
or NUL.
sleepflag Determines whether caller can sleep for memory.
Possible flags are KMSLEP to allow sleeping
until memory is available, or KMNOSLEP to
return NUL immediately if memory is not avail-
able.
DESCRIPTION
The bioclone() function returns an initialized buffer to
perform I/O to a portion of another buffer. The new buffer
will be set up to perform I/O to the range within the
SunOS 5.11 Last change: 16 Jan 2006 1
Kernel Functions for Drivers bioclone(9F)
original I/O request specified by the parameters off and
len. An offset 0 starts the new I/O request at the same
address as the original request. off ] len must not exceed
bbcount, the length of the original request. The device
number dev specifies the device to which the buffer is to
perform I/O. blkno is the block number on device. It will be
assigned to the bblkno field of the cloned buffer struc-
ture. iodone lets the driver identify a specific biodone(9F)
routine to be called by the driver when the I/O is complete.
bpmem determines from where the space for the buffer should
be allocated. If bpmem is NUL, bioclone() will allocate a
new buffer using getrbuf(9F). If sleepflag is set to
KMSLEP, the driver may sleep until space is freed up. If
sleepflag is set to KMNOSLEP, the driver will not sleep.
In either case, a pointer to the allocated space is returned
or NUL to indicate that no space was available. After the
transfer is completed, the buffer has to be freed using
freerbuf(9F). If bpmem is not NUL, it will be used as the
space for the buffer structure. The driver has to ensure
that bpmem is initialized properly either using getrbuf(9F)
or bioinit(9F).
If the original buffer is mapped into the kernel virtual
address space using bpmapin(9F) before calling bioclone(),
a clone buffer will share the kernel mapping of the original
buffer. An additional bpmapin() to get a kernel mapping for
the clone buffer is not necessary.
The driver has to ensure that the original buffer is not
freed while any of the clone buffers is still performing
I/O. The biodone() function has to be called on all clone
buffers before it is called on the original buffer.
RETURN VALUES
The bioclone() function returns a pointer to the initialized
buffer header, or NUL if no space is available.
CONTEXT
The bioclone() function can be called from user, interrup,
or interrupt context. Drivers must not allow bioclone() to
sleep if called from an interrupt routine.
EXAMPLES
Example 1 Using bioclone() for Disk Striping
A device driver can use bioclone() for disk striping. For
each disk in the stripe, a clone buffer is created which
performs I/O to a portion of the original buffer.
SunOS 5.11 Last change: 16 Jan 2006 2
Kernel Functions for Drivers bioclone(9F)
static int
stripestrategy(struct buf *bp)
{
...
bporig = bp;
bp1 = bioclone(bporig, 0, size1, dev1, blkno1,
stripedone, NUL, KMSLEP);
fragment];
...
bpn = bioclone(bporig, offsetn, sizen, devn,
blknon, stripedone, NUL, KMSLEP);
fragment];
/* submit bp1 ... bpn to device */
xxstrategy(bpx);
return (0);
}
static uintt
xxintr(caddrt arg)
{
...
/*
* get bp of completed subrequest. biodone(9F) will
* call stripedone()
*/
biodone(bp);
return (0);
}
static int
stripedone(struct buf *bp)
{
...
freerbuf(bp);
fragment--;
if (fragment == 0) {
/* get bporig */
biodone(bporig);
}
return (0);
}
SEE ALSO
biodone(9F), bpmapin(9F), freerbuf(9F), getrbuf(9F),
buf(9S)
Writing Device Drivers
SunOS 5.11 Last change: 16 Jan 2006 3
|