Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
#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);
Pointer to the buf(9S) structure describing the original I/O request.
Offset within original I/O request where new I/O request should start.
Length of the I/O request.
Device number.
Block number on device.
Specific biodone(9F) routine.
Pointer to a buffer structure to be filled in or NULL.
Determines whether caller can sleep for memory. Possible flags are KM_SLEEP to allow sleeping until memory is available, or KM_NOSLEEP to return NULL immediately if memory is not available.
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.
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); }
Writing Device Drivers