1bioclone(9F) Kernel Functions for Drivers bioclone(9F)
2
3
4
6 bioclone - clone another buffer
7
9 #include <sys/ddi.h>
10 #include <sys/sunddi.h>
11
12 struct buf *bioclone(struct buf *bp, off_t off, size_t len, dev_t dev,
13 daddr_t blkno, int (*iodone) (struct buf *), struct buf *bp_mem,
14 int sleepflag);
15
16
18 Solaris DDI specific (Solaris DDI).
19
21 bp Pointer to the buf(9S) structure describing the original
22 I/O request.
23
24
25 off Offset within original I/O request where new I/O request
26 should start.
27
28
29 len Length of the I/O request.
30
31
32 dev Device number.
33
34
35 blkno Block number on device.
36
37
38 iodone Specific biodone(9F) routine.
39
40
41 bp_mem Pointer to a buffer structure to be filled in or NULL.
42
43
44 sleepflag Determines whether caller can sleep for memory. Possible
45 flags are KM_SLEEP to allow sleeping until memory is
46 available, or KM_NOSLEEP to return NULL immediately if
47 memory is not available.
48
49
51 The bioclone() function returns an initialized buffer to perform I/O to
52 a portion of another buffer. The new buffer will be set up to perform
53 I/O to the range within the original I/O request specified by the
54 parameters off and len. An offset 0 starts the new I/O request at the
55 same address as the original request. off + len must not exceed
56 b_bcount, the length of the original request. The device number dev
57 specifies the device to which the buffer is to perform I/O. blkno is
58 the block number on device. It will be assigned to the b_blkno field of
59 the cloned buffer structure. iodone lets the driver identify a specific
60 biodone(9F) routine to be called by the driver when the I/O is com‐
61 plete. bp_mem determines from where the space for the buffer should be
62 allocated. If bp_mem is NULL, bioclone() will allocate a new buffer
63 using getrbuf(9F). If sleepflag is set to KM_SLEEP, the driver may
64 sleep until space is freed up. If sleepflag is set to KM_NOSLEEP, the
65 driver will not sleep. In either case, a pointer to the allocated space
66 is returned or NULL to indicate that no space was available. After the
67 transfer is completed, the buffer has to be freed using freerbuf(9F).
68 If bp_mem is not NULL, it will be used as the space for the buffer
69 structure. The driver has to ensure that bp_mem is initialized properly
70 either using getrbuf(9F) or bioinit(9F).
71
72
73 If the original buffer is mapped into the kernel virtual address space
74 using bp_mapin(9F) before calling bioclone(), a clone buffer will share
75 the kernel mapping of the original buffer. An additional bp_mapin() to
76 get a kernel mapping for the clone buffer is not necessary.
77
78
79 The driver has to ensure that the original buffer is not freed while
80 any of the clone buffers is still performing I/O. The biodone() func‐
81 tion has to be called on all clone buffers before it is called on the
82 original buffer.
83
85 The bioclone() function returns a pointer to the initialized buffer
86 header, or NULL if no space is available.
87
89 The bioclone() function can be called from user, interrup, or interrupt
90 context. Drivers must not allow bioclone() to sleep if called from an
91 interrupt routine.
92
94 Example 1 Using bioclone() for Disk Striping
95
96
97 A device driver can use bioclone() for disk striping. For each disk in
98 the stripe, a clone buffer is created which performs I/O to a portion
99 of the original buffer.
100
101
102 static int
103 stripe_strategy(struct buf *bp)
104 {
105 ...
106 bp_orig = bp;
107 bp_1 = bioclone(bp_orig, 0, size_1, dev_1, blkno_1,
108 stripe_done, NULL, KM_SLEEP);
109 fragment++;
110 ...
111 bp_n = bioclone(bp_orig, offset_n, size_n, dev_n,
112 blkno_n, stripe_done, NULL, KM_SLEEP);
113 fragment++;
114 /* submit bp_1 ... bp_n to device */
115 xxstrategy(bp_x);
116 return (0);
117 }
118
119 static uint_t
120 xxintr(caddr_t arg)
121 {
122 ...
123 /*
124 * get bp of completed subrequest. biodone(9F) will
125 * call stripe_done()
126 */
127 biodone(bp);
128 return (0);
129 }
130
131 static int
132 stripe_done(struct buf *bp)
133 {
134 ...
135 freerbuf(bp);
136 fragment--;
137 if (fragment == 0) {
138 /* get bp_orig */
139 biodone(bp_orig);
140 }
141 return (0);
142 }
143
144
146 biodone(9F), bp_mapin(9F), freerbuf(9F), getrbuf(9F), buf(9S)
147
148
149 Writing Device Drivers
150
151
152
153SunOS 5.11 16 Jan 2006 bioclone(9F)