1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998,2001 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate * All rights reserved.
25*7c478bd9Sstevel@tonic-gate *
26*7c478bd9Sstevel@tonic-gate */
27*7c478bd9Sstevel@tonic-gate
28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
36*7c478bd9Sstevel@tonic-gate
37*7c478bd9Sstevel@tonic-gate #include <sys/fdbuffer.h>
38*7c478bd9Sstevel@tonic-gate
39*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
40*7c478bd9Sstevel@tonic-gate static int fdb_debug;
41*7c478bd9Sstevel@tonic-gate #define FDB_D_CREATE 001
42*7c478bd9Sstevel@tonic-gate #define FDB_D_ALLOC 002
43*7c478bd9Sstevel@tonic-gate #define FDB_D_IO 004
44*7c478bd9Sstevel@tonic-gate #define FDB_D_ASYNC 010
45*7c478bd9Sstevel@tonic-gate #define DEBUGF(lvl, args) { if ((lvl) & fdb_debug) cmn_err args; }
46*7c478bd9Sstevel@tonic-gate #else
47*7c478bd9Sstevel@tonic-gate #define DEBUGF(level, args)
48*7c478bd9Sstevel@tonic-gate #endif
49*7c478bd9Sstevel@tonic-gate static struct kmem_cache *fdb_cache;
50*7c478bd9Sstevel@tonic-gate static void fdb_zero_holes(fdbuffer_t *fdb);
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
53*7c478bd9Sstevel@tonic-gate static int
fdb_cache_constructor(void * buf,void * cdrarg,int kmflags)54*7c478bd9Sstevel@tonic-gate fdb_cache_constructor(void *buf, void *cdrarg, int kmflags)
55*7c478bd9Sstevel@tonic-gate {
56*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = buf;
57*7c478bd9Sstevel@tonic-gate
58*7c478bd9Sstevel@tonic-gate mutex_init(&fdb->fd_mutex, NULL, MUTEX_DEFAULT, NULL);
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate return (0);
61*7c478bd9Sstevel@tonic-gate }
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
64*7c478bd9Sstevel@tonic-gate static void
fdb_cache_destructor(void * buf,void * cdrarg)65*7c478bd9Sstevel@tonic-gate fdb_cache_destructor(void *buf, void *cdrarg)
66*7c478bd9Sstevel@tonic-gate {
67*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = buf;
68*7c478bd9Sstevel@tonic-gate
69*7c478bd9Sstevel@tonic-gate mutex_destroy(&fdb->fd_mutex);
70*7c478bd9Sstevel@tonic-gate }
71*7c478bd9Sstevel@tonic-gate
72*7c478bd9Sstevel@tonic-gate void
fdb_init()73*7c478bd9Sstevel@tonic-gate fdb_init()
74*7c478bd9Sstevel@tonic-gate {
75*7c478bd9Sstevel@tonic-gate fdb_cache = kmem_cache_create("fdb_cache", sizeof (fdbuffer_t),
76*7c478bd9Sstevel@tonic-gate 0, fdb_cache_constructor, fdb_cache_destructor,
77*7c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0);
78*7c478bd9Sstevel@tonic-gate }
79*7c478bd9Sstevel@tonic-gate
80*7c478bd9Sstevel@tonic-gate static void
fdb_prepare(fdbuffer_t * fdb)81*7c478bd9Sstevel@tonic-gate fdb_prepare(fdbuffer_t *fdb)
82*7c478bd9Sstevel@tonic-gate {
83*7c478bd9Sstevel@tonic-gate fdb->fd_holes = NULL;
84*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc = NULL;
85*7c478bd9Sstevel@tonic-gate fdb->fd_iargp = NULL;
86*7c478bd9Sstevel@tonic-gate fdb->fd_parentbp = NULL;
87*7c478bd9Sstevel@tonic-gate fdb->fd_resid = 0;
88*7c478bd9Sstevel@tonic-gate fdb->fd_iocount = 0;
89*7c478bd9Sstevel@tonic-gate fdb->fd_iodispatch = 0;
90*7c478bd9Sstevel@tonic-gate fdb->fd_err = 0;
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate
93*7c478bd9Sstevel@tonic-gate fdbuffer_t *
fdb_page_create(page_t * pp,size_t len,int flags)94*7c478bd9Sstevel@tonic-gate fdb_page_create(page_t *pp, size_t len, int flags)
95*7c478bd9Sstevel@tonic-gate {
96*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb;
97*7c478bd9Sstevel@tonic-gate
98*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE,
99*7c478bd9Sstevel@tonic-gate "?fdb_page_create: pp: %p len: %lux flags: %x",
100*7c478bd9Sstevel@tonic-gate (void *)pp, len, flags));
101*7c478bd9Sstevel@tonic-gate
102*7c478bd9Sstevel@tonic-gate ASSERT(flags & (FDB_READ|FDB_WRITE));
103*7c478bd9Sstevel@tonic-gate
104*7c478bd9Sstevel@tonic-gate fdb = kmem_cache_alloc(fdb_cache, KM_SLEEP);
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate fdb_prepare(fdb);
107*7c478bd9Sstevel@tonic-gate
108*7c478bd9Sstevel@tonic-gate fdb->fd_type = FDB_PAGEIO;
109*7c478bd9Sstevel@tonic-gate fdb->fd_len = len;
110*7c478bd9Sstevel@tonic-gate fdb->fd_state = flags;
111*7c478bd9Sstevel@tonic-gate fdb->fd_pages = pp;
112*7c478bd9Sstevel@tonic-gate
113*7c478bd9Sstevel@tonic-gate return (fdb);
114*7c478bd9Sstevel@tonic-gate }
115*7c478bd9Sstevel@tonic-gate
116*7c478bd9Sstevel@tonic-gate fdbuffer_t *
fdb_addr_create(caddr_t addr,size_t len,int flags,page_t ** pplist,struct proc * procp)117*7c478bd9Sstevel@tonic-gate fdb_addr_create(
118*7c478bd9Sstevel@tonic-gate caddr_t addr,
119*7c478bd9Sstevel@tonic-gate size_t len,
120*7c478bd9Sstevel@tonic-gate int flags,
121*7c478bd9Sstevel@tonic-gate page_t **pplist,
122*7c478bd9Sstevel@tonic-gate struct proc *procp)
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb;
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE,
127*7c478bd9Sstevel@tonic-gate "?fdb_addr_create: addr: %p len: %lux flags: %x",
128*7c478bd9Sstevel@tonic-gate (void *)addr, len, flags));
129*7c478bd9Sstevel@tonic-gate
130*7c478bd9Sstevel@tonic-gate ASSERT(flags & (FDB_READ|FDB_WRITE));
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate fdb = kmem_cache_alloc(fdb_cache, KM_SLEEP);
133*7c478bd9Sstevel@tonic-gate
134*7c478bd9Sstevel@tonic-gate fdb_prepare(fdb);
135*7c478bd9Sstevel@tonic-gate
136*7c478bd9Sstevel@tonic-gate fdb->fd_type = FDB_VADDR;
137*7c478bd9Sstevel@tonic-gate fdb->fd_len = len;
138*7c478bd9Sstevel@tonic-gate fdb->fd_state = flags;
139*7c478bd9Sstevel@tonic-gate fdb->fd_addr = addr;
140*7c478bd9Sstevel@tonic-gate fdb->fd_shadow = pplist;
141*7c478bd9Sstevel@tonic-gate fdb->fd_procp = procp;
142*7c478bd9Sstevel@tonic-gate
143*7c478bd9Sstevel@tonic-gate return (fdb);
144*7c478bd9Sstevel@tonic-gate }
145*7c478bd9Sstevel@tonic-gate
146*7c478bd9Sstevel@tonic-gate void
fdb_set_iofunc(fdbuffer_t * fdb,fdb_iodone_t iofunc,void * ioargp,int flag)147*7c478bd9Sstevel@tonic-gate fdb_set_iofunc(fdbuffer_t *fdb, fdb_iodone_t iofunc, void *ioargp, int flag)
148*7c478bd9Sstevel@tonic-gate {
149*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
150*7c478bd9Sstevel@tonic-gate ASSERT(iofunc);
151*7c478bd9Sstevel@tonic-gate ASSERT((flag & ~FDB_ICALLBACK) == 0);
152*7c478bd9Sstevel@tonic-gate
153*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc = iofunc;
154*7c478bd9Sstevel@tonic-gate fdb->fd_iargp = ioargp;
155*7c478bd9Sstevel@tonic-gate
156*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
157*7c478bd9Sstevel@tonic-gate
158*7c478bd9Sstevel@tonic-gate if (flag & FDB_ICALLBACK)
159*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ICALLBACK;
160*7c478bd9Sstevel@tonic-gate
161*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ASYNC;
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate int
fdb_get_error(fdbuffer_t * fdb)167*7c478bd9Sstevel@tonic-gate fdb_get_error(fdbuffer_t *fdb)
168*7c478bd9Sstevel@tonic-gate {
169*7c478bd9Sstevel@tonic-gate return (fdb->fd_err);
170*7c478bd9Sstevel@tonic-gate }
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate void
fdb_free(fdbuffer_t * fdb)173*7c478bd9Sstevel@tonic-gate fdb_free(fdbuffer_t *fdb)
174*7c478bd9Sstevel@tonic-gate {
175*7c478bd9Sstevel@tonic-gate fdb_holes_t *fdh, *fdhp;
176*7c478bd9Sstevel@tonic-gate
177*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE, "?fdb_free: addr: %p flags: %x",
178*7c478bd9Sstevel@tonic-gate (void *)fdb, fdb->fd_state));
179*7c478bd9Sstevel@tonic-gate
180*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
181*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch == 0);
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate if (fdb->fd_state & FDB_ZEROHOLE) {
184*7c478bd9Sstevel@tonic-gate fdb_zero_holes(fdb);
185*7c478bd9Sstevel@tonic-gate }
186*7c478bd9Sstevel@tonic-gate
187*7c478bd9Sstevel@tonic-gate for (fdh = fdb->fd_holes; fdh; ) {
188*7c478bd9Sstevel@tonic-gate fdhp = fdh;
189*7c478bd9Sstevel@tonic-gate fdh = fdh->next_hole;
190*7c478bd9Sstevel@tonic-gate kmem_free(fdhp, sizeof (fdb_holes_t));
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate
193*7c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp != NULL) {
194*7c478bd9Sstevel@tonic-gate switch (fdb->fd_type) {
195*7c478bd9Sstevel@tonic-gate case FDB_PAGEIO:
196*7c478bd9Sstevel@tonic-gate pageio_done(fdb->fd_parentbp);
197*7c478bd9Sstevel@tonic-gate break;
198*7c478bd9Sstevel@tonic-gate case FDB_VADDR:
199*7c478bd9Sstevel@tonic-gate kmem_free(fdb->fd_parentbp, sizeof (struct buf));
200*7c478bd9Sstevel@tonic-gate break;
201*7c478bd9Sstevel@tonic-gate default:
202*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?fdb_free: Unknown fdb type.");
203*7c478bd9Sstevel@tonic-gate break;
204*7c478bd9Sstevel@tonic-gate }
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gate kmem_cache_free(fdb_cache, fdb);
208*7c478bd9Sstevel@tonic-gate
209*7c478bd9Sstevel@tonic-gate }
210*7c478bd9Sstevel@tonic-gate
211*7c478bd9Sstevel@tonic-gate /*
212*7c478bd9Sstevel@tonic-gate * The offset should be from the begining of the buffer
213*7c478bd9Sstevel@tonic-gate * it has nothing to do with file offset. This fact should be
214*7c478bd9Sstevel@tonic-gate * reflected in the caller of this routine.
215*7c478bd9Sstevel@tonic-gate */
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate void
fdb_add_hole(fdbuffer_t * fdb,u_offset_t off,size_t len)218*7c478bd9Sstevel@tonic-gate fdb_add_hole(fdbuffer_t *fdb, u_offset_t off, size_t len)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate fdb_holes_t *this_hole;
221*7c478bd9Sstevel@tonic-gate
222*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
223*7c478bd9Sstevel@tonic-gate ASSERT(off < fdb->fd_len);
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE, "?fdb_add_hole: off %llx len %lx",
226*7c478bd9Sstevel@tonic-gate off, len));
227*7c478bd9Sstevel@tonic-gate
228*7c478bd9Sstevel@tonic-gate this_hole = kmem_alloc(sizeof (fdb_holes_t), KM_SLEEP);
229*7c478bd9Sstevel@tonic-gate this_hole->off = off;
230*7c478bd9Sstevel@tonic-gate this_hole->len = len;
231*7c478bd9Sstevel@tonic-gate
232*7c478bd9Sstevel@tonic-gate if (fdb->fd_holes == NULL || off < fdb->fd_holes->off) {
233*7c478bd9Sstevel@tonic-gate this_hole->next_hole = fdb->fd_holes;
234*7c478bd9Sstevel@tonic-gate fdb->fd_holes = this_hole;
235*7c478bd9Sstevel@tonic-gate } else {
236*7c478bd9Sstevel@tonic-gate fdb_holes_t *fdhp = fdb->fd_holes;
237*7c478bd9Sstevel@tonic-gate
238*7c478bd9Sstevel@tonic-gate while (fdhp->next_hole && off > fdhp->next_hole->off)
239*7c478bd9Sstevel@tonic-gate fdhp = fdhp->next_hole;
240*7c478bd9Sstevel@tonic-gate
241*7c478bd9Sstevel@tonic-gate this_hole->next_hole = fdhp->next_hole;
242*7c478bd9Sstevel@tonic-gate fdhp->next_hole = this_hole;
243*7c478bd9Sstevel@tonic-gate }
244*7c478bd9Sstevel@tonic-gate
245*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
246*7c478bd9Sstevel@tonic-gate
247*7c478bd9Sstevel@tonic-gate fdb->fd_iocount += len;
248*7c478bd9Sstevel@tonic-gate
249*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate
252*7c478bd9Sstevel@tonic-gate fdb_holes_t *
fdb_get_holes(fdbuffer_t * fdb)253*7c478bd9Sstevel@tonic-gate fdb_get_holes(fdbuffer_t *fdb)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
256*7c478bd9Sstevel@tonic-gate
257*7c478bd9Sstevel@tonic-gate if (fdb->fd_state & FDB_ZEROHOLE) {
258*7c478bd9Sstevel@tonic-gate fdb_zero_holes(fdb);
259*7c478bd9Sstevel@tonic-gate }
260*7c478bd9Sstevel@tonic-gate
261*7c478bd9Sstevel@tonic-gate return (fdb->fd_holes);
262*7c478bd9Sstevel@tonic-gate }
263*7c478bd9Sstevel@tonic-gate
264*7c478bd9Sstevel@tonic-gate /*
265*7c478bd9Sstevel@tonic-gate * Note that offsets refer to offsets from the begining of the buffer
266*7c478bd9Sstevel@tonic-gate * and as such the memory should be cleared accordingly.
267*7c478bd9Sstevel@tonic-gate */
268*7c478bd9Sstevel@tonic-gate
269*7c478bd9Sstevel@tonic-gate static void
fdb_zero_holes(fdbuffer_t * fdb)270*7c478bd9Sstevel@tonic-gate fdb_zero_holes(fdbuffer_t *fdb)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate fdb_holes_t *fdh = fdb->fd_holes;
273*7c478bd9Sstevel@tonic-gate page_t *pp;
274*7c478bd9Sstevel@tonic-gate
275*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
276*7c478bd9Sstevel@tonic-gate
277*7c478bd9Sstevel@tonic-gate if (!fdh)
278*7c478bd9Sstevel@tonic-gate return;
279*7c478bd9Sstevel@tonic-gate
280*7c478bd9Sstevel@tonic-gate switch (fdb->fd_type) {
281*7c478bd9Sstevel@tonic-gate case FDB_PAGEIO:
282*7c478bd9Sstevel@tonic-gate pp = fdb->fd_pages;
283*7c478bd9Sstevel@tonic-gate while (fdh) {
284*7c478bd9Sstevel@tonic-gate fdb_holes_t *pfdh = fdh;
285*7c478bd9Sstevel@tonic-gate size_t l = fdh->len;
286*7c478bd9Sstevel@tonic-gate u_offset_t o = fdh->off;
287*7c478bd9Sstevel@tonic-gate ASSERT(pp);
288*7c478bd9Sstevel@tonic-gate
289*7c478bd9Sstevel@tonic-gate do {
290*7c478bd9Sstevel@tonic-gate int zerolen;
291*7c478bd9Sstevel@tonic-gate ASSERT(o >= pp->p_offset);
292*7c478bd9Sstevel@tonic-gate
293*7c478bd9Sstevel@tonic-gate /*
294*7c478bd9Sstevel@tonic-gate * This offset is wrong since
295*7c478bd9Sstevel@tonic-gate * the offset passed from the pages
296*7c478bd9Sstevel@tonic-gate * perspective starts at some virtual
297*7c478bd9Sstevel@tonic-gate * address but the hole is relative
298*7c478bd9Sstevel@tonic-gate * to the beginning of the fdbuffer.
299*7c478bd9Sstevel@tonic-gate */
300*7c478bd9Sstevel@tonic-gate if (o >= pp->p_offset + PAGESIZE)
301*7c478bd9Sstevel@tonic-gate continue;
302*7c478bd9Sstevel@tonic-gate
303*7c478bd9Sstevel@tonic-gate zerolen = min(PAGESIZE, l);
304*7c478bd9Sstevel@tonic-gate
305*7c478bd9Sstevel@tonic-gate ASSERT(zerolen > 0);
306*7c478bd9Sstevel@tonic-gate ASSERT(zerolen <= PAGESIZE);
307*7c478bd9Sstevel@tonic-gate
308*7c478bd9Sstevel@tonic-gate pagezero(pp, ((uintptr_t)o & PAGEOFFSET),
309*7c478bd9Sstevel@tonic-gate zerolen);
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate l -= zerolen;
312*7c478bd9Sstevel@tonic-gate o += zerolen;
313*7c478bd9Sstevel@tonic-gate
314*7c478bd9Sstevel@tonic-gate if (l == 0)
315*7c478bd9Sstevel@tonic-gate break;
316*7c478bd9Sstevel@tonic-gate
317*7c478bd9Sstevel@tonic-gate } while (pp = page_list_next(pp));
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate if (!pp)
320*7c478bd9Sstevel@tonic-gate break;
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate fdh = fdh->next_hole;
323*7c478bd9Sstevel@tonic-gate kmem_free(pfdh, sizeof (fdb_holes_t));
324*7c478bd9Sstevel@tonic-gate }
325*7c478bd9Sstevel@tonic-gate break;
326*7c478bd9Sstevel@tonic-gate case FDB_VADDR:
327*7c478bd9Sstevel@tonic-gate while (fdh) {
328*7c478bd9Sstevel@tonic-gate fdb_holes_t *pfdh = fdh;
329*7c478bd9Sstevel@tonic-gate
330*7c478bd9Sstevel@tonic-gate bzero(fdb->fd_addr + fdh->off, fdh->len);
331*7c478bd9Sstevel@tonic-gate
332*7c478bd9Sstevel@tonic-gate fdh = fdh->next_hole;
333*7c478bd9Sstevel@tonic-gate kmem_free(pfdh, sizeof (fdb_holes_t));
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate default:
336*7c478bd9Sstevel@tonic-gate panic("fdb_zero_holes: Unknown fdb type.");
337*7c478bd9Sstevel@tonic-gate break;
338*7c478bd9Sstevel@tonic-gate }
339*7c478bd9Sstevel@tonic-gate }
340*7c478bd9Sstevel@tonic-gate
341*7c478bd9Sstevel@tonic-gate
342*7c478bd9Sstevel@tonic-gate buf_t *
fdb_iosetup(fdbuffer_t * fdb,u_offset_t off,size_t len,struct vnode * vp,int b_flags)343*7c478bd9Sstevel@tonic-gate fdb_iosetup(fdbuffer_t *fdb, u_offset_t off, size_t len, struct vnode *vp,
344*7c478bd9Sstevel@tonic-gate int b_flags)
345*7c478bd9Sstevel@tonic-gate {
346*7c478bd9Sstevel@tonic-gate buf_t *bp;
347*7c478bd9Sstevel@tonic-gate
348*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE,
349*7c478bd9Sstevel@tonic-gate "?fdb_iosetup: off: %llx len: %lux fdb: len: %lux flags: %x",
350*7c478bd9Sstevel@tonic-gate off, len, fdb->fd_len, fdb->fd_state));
351*7c478bd9Sstevel@tonic-gate
352*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
353*7c478bd9Sstevel@tonic-gate
354*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
355*7c478bd9Sstevel@tonic-gate
356*7c478bd9Sstevel@tonic-gate ASSERT(((b_flags & B_READ) && (fdb->fd_state & FDB_READ)) ||
357*7c478bd9Sstevel@tonic-gate ((b_flags & B_WRITE) && (fdb->fd_state & FDB_WRITE)));
358*7c478bd9Sstevel@tonic-gate /*
359*7c478bd9Sstevel@tonic-gate * The fdb can be used either in sync or async mode, if the
360*7c478bd9Sstevel@tonic-gate * buffer has not been used it may be used in either mode, but
361*7c478bd9Sstevel@tonic-gate * once you have started to use the buf in either mode all
362*7c478bd9Sstevel@tonic-gate * subsequent i/o requests must take place the same way.
363*7c478bd9Sstevel@tonic-gate */
364*7c478bd9Sstevel@tonic-gate
365*7c478bd9Sstevel@tonic-gate ASSERT(((b_flags & B_ASYNC) &&
366*7c478bd9Sstevel@tonic-gate ((fdb->fd_state & FDB_ASYNC) || !(fdb->fd_state & FDB_SYNC))) ||
367*7c478bd9Sstevel@tonic-gate (!(b_flags & B_ASYNC) &&
368*7c478bd9Sstevel@tonic-gate ((fdb->fd_state & FDB_SYNC) || !(fdb->fd_state & FDB_ASYNC))));
369*7c478bd9Sstevel@tonic-gate
370*7c478bd9Sstevel@tonic-gate
371*7c478bd9Sstevel@tonic-gate fdb->fd_state |= b_flags & B_ASYNC ? FDB_ASYNC : FDB_SYNC;
372*7c478bd9Sstevel@tonic-gate
373*7c478bd9Sstevel@tonic-gate fdb->fd_iodispatch++;
374*7c478bd9Sstevel@tonic-gate
375*7c478bd9Sstevel@tonic-gate ASSERT((fdb->fd_state & FDB_ASYNC && fdb->fd_iofunc != NULL) ||
376*7c478bd9Sstevel@tonic-gate fdb->fd_state & FDB_SYNC);
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
379*7c478bd9Sstevel@tonic-gate
380*7c478bd9Sstevel@tonic-gate ASSERT((len & (DEV_BSIZE - 1)) == 0);
381*7c478bd9Sstevel@tonic-gate ASSERT(off+len <= fdb->fd_len);
382*7c478bd9Sstevel@tonic-gate
383*7c478bd9Sstevel@tonic-gate switch (fdb->fd_type) {
384*7c478bd9Sstevel@tonic-gate case FDB_PAGEIO:
385*7c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp == NULL) {
386*7c478bd9Sstevel@tonic-gate bp = pageio_setup(fdb->fd_pages, len, vp, b_flags);
387*7c478bd9Sstevel@tonic-gate fdb->fd_parentbp = bp;
388*7c478bd9Sstevel@tonic-gate }
389*7c478bd9Sstevel@tonic-gate break;
390*7c478bd9Sstevel@tonic-gate case FDB_VADDR:
391*7c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp == NULL) {
392*7c478bd9Sstevel@tonic-gate
393*7c478bd9Sstevel@tonic-gate bp = kmem_alloc(sizeof (buf_t), KM_SLEEP);
394*7c478bd9Sstevel@tonic-gate bioinit(bp);
395*7c478bd9Sstevel@tonic-gate bp->b_error = 0;
396*7c478bd9Sstevel@tonic-gate bp->b_proc = fdb->fd_procp;
397*7c478bd9Sstevel@tonic-gate bp->b_flags = b_flags | B_BUSY | B_PHYS;
398*7c478bd9Sstevel@tonic-gate bp->b_bcount = len;
399*7c478bd9Sstevel@tonic-gate bp->b_un.b_addr = fdb->fd_addr;
400*7c478bd9Sstevel@tonic-gate bp->b_shadow = fdb->fd_shadow;
401*7c478bd9Sstevel@tonic-gate if (fdb->fd_shadow != NULL)
402*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_SHADOW;
403*7c478bd9Sstevel@tonic-gate fdb->fd_parentbp = bp;
404*7c478bd9Sstevel@tonic-gate }
405*7c478bd9Sstevel@tonic-gate break;
406*7c478bd9Sstevel@tonic-gate default:
407*7c478bd9Sstevel@tonic-gate panic("fdb_iosetup: Unsupported fdb type.");
408*7c478bd9Sstevel@tonic-gate break;
409*7c478bd9Sstevel@tonic-gate };
410*7c478bd9Sstevel@tonic-gate
411*7c478bd9Sstevel@tonic-gate bp = bioclone(fdb->fd_parentbp, off, len, 0, 0,
412*7c478bd9Sstevel@tonic-gate (b_flags & B_ASYNC) ? (int (*)())fdb_iodone : NULL,
413*7c478bd9Sstevel@tonic-gate NULL, KM_SLEEP);
414*7c478bd9Sstevel@tonic-gate
415*7c478bd9Sstevel@tonic-gate bp->b_forw = (struct buf *)fdb;
416*7c478bd9Sstevel@tonic-gate
417*7c478bd9Sstevel@tonic-gate if (b_flags & B_ASYNC)
418*7c478bd9Sstevel@tonic-gate bp->b_flags |= B_ASYNC;
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate return (bp);
421*7c478bd9Sstevel@tonic-gate }
422*7c478bd9Sstevel@tonic-gate
423*7c478bd9Sstevel@tonic-gate size_t
fdb_get_iolen(fdbuffer_t * fdb)424*7c478bd9Sstevel@tonic-gate fdb_get_iolen(fdbuffer_t *fdb)
425*7c478bd9Sstevel@tonic-gate {
426*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
427*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch == 0);
428*7c478bd9Sstevel@tonic-gate
429*7c478bd9Sstevel@tonic-gate return (fdb->fd_iocount - fdb->fd_resid);
430*7c478bd9Sstevel@tonic-gate }
431*7c478bd9Sstevel@tonic-gate
432*7c478bd9Sstevel@tonic-gate void
fdb_ioerrdone(fdbuffer_t * fdb,int error)433*7c478bd9Sstevel@tonic-gate fdb_ioerrdone(fdbuffer_t *fdb, int error)
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
436*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_state & FDB_ASYNC);
437*7c478bd9Sstevel@tonic-gate
438*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE,
439*7c478bd9Sstevel@tonic-gate "?fdb_ioerrdone: fdb: len: %lux flags: %x error: %d",
440*7c478bd9Sstevel@tonic-gate fdb->fd_len, fdb->fd_state, error));
441*7c478bd9Sstevel@tonic-gate
442*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
443*7c478bd9Sstevel@tonic-gate
444*7c478bd9Sstevel@tonic-gate fdb->fd_err = error;
445*7c478bd9Sstevel@tonic-gate
446*7c478bd9Sstevel@tonic-gate if (error)
447*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ERROR;
448*7c478bd9Sstevel@tonic-gate else
449*7c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_DONE;
450*7c478bd9Sstevel@tonic-gate
451*7c478bd9Sstevel@tonic-gate /*
452*7c478bd9Sstevel@tonic-gate * If there is outstanding i/o return wainting for i/o's to complete.
453*7c478bd9Sstevel@tonic-gate */
454*7c478bd9Sstevel@tonic-gate if (fdb->fd_iodispatch > 0) {
455*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
456*7c478bd9Sstevel@tonic-gate return;
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate
459*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
460*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, NULL);
461*7c478bd9Sstevel@tonic-gate }
462*7c478bd9Sstevel@tonic-gate
463*7c478bd9Sstevel@tonic-gate void
fdb_iodone(buf_t * bp)464*7c478bd9Sstevel@tonic-gate fdb_iodone(buf_t *bp)
465*7c478bd9Sstevel@tonic-gate {
466*7c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = (fdbuffer_t *)bp->b_forw;
467*7c478bd9Sstevel@tonic-gate int error, isasync;
468*7c478bd9Sstevel@tonic-gate int icallback;
469*7c478bd9Sstevel@tonic-gate
470*7c478bd9Sstevel@tonic-gate ASSERT(fdb);
471*7c478bd9Sstevel@tonic-gate
472*7c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE,
473*7c478bd9Sstevel@tonic-gate "?fdb_iodone: fdb: len: %lux flags: %x error: %d",
474*7c478bd9Sstevel@tonic-gate fdb->fd_len, fdb->fd_state, geterror(bp)));
475*7c478bd9Sstevel@tonic-gate
476*7c478bd9Sstevel@tonic-gate if (bp->b_flags & B_REMAPPED)
477*7c478bd9Sstevel@tonic-gate bp_mapout(bp);
478*7c478bd9Sstevel@tonic-gate
479*7c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
480*7c478bd9Sstevel@tonic-gate
481*7c478bd9Sstevel@tonic-gate icallback = fdb->fd_state & FDB_ICALLBACK;
482*7c478bd9Sstevel@tonic-gate isasync = fdb->fd_state & FDB_ASYNC;
483*7c478bd9Sstevel@tonic-gate
484*7c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch > 0);
485*7c478bd9Sstevel@tonic-gate fdb->fd_iodispatch--;
486*7c478bd9Sstevel@tonic-gate
487*7c478bd9Sstevel@tonic-gate if (error = geterror(bp)) {
488*7c478bd9Sstevel@tonic-gate fdb->fd_err = error;
489*7c478bd9Sstevel@tonic-gate if (bp->b_resid)
490*7c478bd9Sstevel@tonic-gate fdb->fd_resid += bp->b_resid;
491*7c478bd9Sstevel@tonic-gate else
492*7c478bd9Sstevel@tonic-gate fdb->fd_resid += bp->b_bcount;
493*7c478bd9Sstevel@tonic-gate }
494*7c478bd9Sstevel@tonic-gate
495*7c478bd9Sstevel@tonic-gate fdb->fd_iocount += bp->b_bcount;
496*7c478bd9Sstevel@tonic-gate
497*7c478bd9Sstevel@tonic-gate /*
498*7c478bd9Sstevel@tonic-gate * ioack collects the total amount of i/o accounted for
499*7c478bd9Sstevel@tonic-gate * this includes:
500*7c478bd9Sstevel@tonic-gate *
501*7c478bd9Sstevel@tonic-gate * - i/o completed
502*7c478bd9Sstevel@tonic-gate * - i/o attempted but not completed,
503*7c478bd9Sstevel@tonic-gate * - i/o not done due to holes.
504*7c478bd9Sstevel@tonic-gate *
505*7c478bd9Sstevel@tonic-gate * Once the entire i/o ranges has been accounted for we'll
506*7c478bd9Sstevel@tonic-gate * call the async function associated with the fdb.
507*7c478bd9Sstevel@tonic-gate *
508*7c478bd9Sstevel@tonic-gate */
509*7c478bd9Sstevel@tonic-gate
510*7c478bd9Sstevel@tonic-gate if ((fdb->fd_iodispatch == 0) &&
511*7c478bd9Sstevel@tonic-gate (fdb->fd_state & (FDB_ERROR|FDB_DONE))) {
512*7c478bd9Sstevel@tonic-gate
513*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
514*7c478bd9Sstevel@tonic-gate
515*7c478bd9Sstevel@tonic-gate if (isasync || icallback) {
516*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, bp);
517*7c478bd9Sstevel@tonic-gate }
518*7c478bd9Sstevel@tonic-gate
519*7c478bd9Sstevel@tonic-gate } else {
520*7c478bd9Sstevel@tonic-gate
521*7c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
522*7c478bd9Sstevel@tonic-gate
523*7c478bd9Sstevel@tonic-gate if (icallback) {
524*7c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, bp);
525*7c478bd9Sstevel@tonic-gate }
526*7c478bd9Sstevel@tonic-gate }
527*7c478bd9Sstevel@tonic-gate
528*7c478bd9Sstevel@tonic-gate freerbuf(bp);
529*7c478bd9Sstevel@tonic-gate }
530