bioclone(9F)
NAME
bioclone - clone another buffer
SYNOPSIS
#include <sys/ddi.h> #include <sys/sunddi.h>
struct buf *bioclone(struct buf *bp, off_t off, size_t len,
dev_t dev, daddr_t blkno, int (*iodone) (struct buf *),
struct buf *bp_mem, int sleepflag);
INTERFACE LEVEL
Solaris DDI specific (Solaris DDI).
PARAMETERS
bp Pointer to the buf(9S) structure describing the origi-
nal 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.
bp_mem
Pointer to a buffer structure to be filled in or NULL.
sleepflag
Determines whether caller can sleep for memory. Possi-
ble flags are KM_SLEEP to allow sleeping until memory
is available, or KM_NOSLEEP to return NULL immediately
if memory is not available.
DESCRIPTION
bioclone() 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 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 b_bcount, 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 b_blkno
field of the cloned buffer structure. iodone lets the driver
identify a specific biodone(9F) routine to be called by the
driver when the I/O is complete. bp_mem determines from
where the space for the buffer should be allocated. If
bp_mem is NULL, bioclone() will allocate a new buffer using
getrbuf(9F). If sleepflag is set to KM_SLEEP, the driver
may sleep until space is freed up. If sleepflag is set to
KM_NOSLEEP, the driver will not sleep. In either case, a
pointer to the allocated space is returned or NULL to indi-
cate that no space was available. After the transfer is com-
pleted, the buffer has to be freed using freerbuf(9F). If
bp_mem is not NULL, it will be used as the space for the
buffer structure. The driver has to ensure that bp_mem is
initialized properly either using getrbuf(9F) or
bioinit(9F).
If the original buffer is mapped into the kernel virtual
address space using bp_mapin(9F) before calling bioclone(),
a clone buffer will share the kernel mapping of the original
buffer. An additional bp_mapin() 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 NULL if no space is available.
CONTEXT
bioclone() can be called from user 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.
static int
stripe_strategy(struct buf *bp)
{
...
bp_orig = bp;
bp_1 = bioclone(bp_orig, 0, size_1, dev_1, blkno_1,
stripe_done, NULL, KM_SLEEP);
fragment++;
...
bp_n = bioclone(bp_orig, offset_n, size_n, dev_n,
blkno_n, stripe_done, NULL, KM_SLEEP);
fragment++;
/* submit bp_1 ... bp_n to device */
xxstrategy(bp_x);
return (0);
}
static uint_t
xxintr(caddr_t arg)
{
...
/*
* get bp of completed subrequest. biodone(9F) will
* call stripe_done()
*/
biodone(bp);
return (0);
}
static int
stripe_done(struct buf *bp)
{
...
freerbuf(bp);
fragment--;
if (fragment == 0) {
/* get bp_orig */
biodone(bp_orig);
}
return (0);
}
SEE ALSO
biodone(9F), bp_mapin(9F), freerbuf(9F), getrbuf(9F),
buf(9S)
Writing Device Drivers
Man(1) output converted with
man2html