17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright (c) 1998,2001 by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate * All rights reserved.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
307c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
317c478bd9Sstevel@tonic-gate #include <sys/systm.h>
327c478bd9Sstevel@tonic-gate #include <sys/debug.h>
337c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #include <sys/fdbuffer.h>
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate #ifdef DEBUG
387c478bd9Sstevel@tonic-gate static int fdb_debug;
397c478bd9Sstevel@tonic-gate #define FDB_D_CREATE 001
407c478bd9Sstevel@tonic-gate #define FDB_D_ALLOC 002
417c478bd9Sstevel@tonic-gate #define FDB_D_IO 004
427c478bd9Sstevel@tonic-gate #define FDB_D_ASYNC 010
437c478bd9Sstevel@tonic-gate #define DEBUGF(lvl, args) { if ((lvl) & fdb_debug) cmn_err args; }
447c478bd9Sstevel@tonic-gate #else
457c478bd9Sstevel@tonic-gate #define DEBUGF(level, args)
467c478bd9Sstevel@tonic-gate #endif
477c478bd9Sstevel@tonic-gate static struct kmem_cache *fdb_cache;
487c478bd9Sstevel@tonic-gate static void fdb_zero_holes(fdbuffer_t *fdb);
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /* ARGSUSED */
517c478bd9Sstevel@tonic-gate static int
fdb_cache_constructor(void * buf,void * cdrarg,int kmflags)527c478bd9Sstevel@tonic-gate fdb_cache_constructor(void *buf, void *cdrarg, int kmflags)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = buf;
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate mutex_init(&fdb->fd_mutex, NULL, MUTEX_DEFAULT, NULL);
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate return (0);
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /* ARGSUSED */
627c478bd9Sstevel@tonic-gate static void
fdb_cache_destructor(void * buf,void * cdrarg)637c478bd9Sstevel@tonic-gate fdb_cache_destructor(void *buf, void *cdrarg)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = buf;
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate mutex_destroy(&fdb->fd_mutex);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate void
fdb_init()717c478bd9Sstevel@tonic-gate fdb_init()
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate fdb_cache = kmem_cache_create("fdb_cache", sizeof (fdbuffer_t),
747c478bd9Sstevel@tonic-gate 0, fdb_cache_constructor, fdb_cache_destructor,
757c478bd9Sstevel@tonic-gate NULL, NULL, NULL, 0);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate static void
fdb_prepare(fdbuffer_t * fdb)797c478bd9Sstevel@tonic-gate fdb_prepare(fdbuffer_t *fdb)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate fdb->fd_holes = NULL;
827c478bd9Sstevel@tonic-gate fdb->fd_iofunc = NULL;
837c478bd9Sstevel@tonic-gate fdb->fd_iargp = NULL;
847c478bd9Sstevel@tonic-gate fdb->fd_parentbp = NULL;
857c478bd9Sstevel@tonic-gate fdb->fd_resid = 0;
867c478bd9Sstevel@tonic-gate fdb->fd_iocount = 0;
877c478bd9Sstevel@tonic-gate fdb->fd_iodispatch = 0;
887c478bd9Sstevel@tonic-gate fdb->fd_err = 0;
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate fdbuffer_t *
fdb_page_create(page_t * pp,size_t len,int flags)927c478bd9Sstevel@tonic-gate fdb_page_create(page_t *pp, size_t len, int flags)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate fdbuffer_t *fdb;
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE,
977c478bd9Sstevel@tonic-gate "?fdb_page_create: pp: %p len: %lux flags: %x",
987c478bd9Sstevel@tonic-gate (void *)pp, len, flags));
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate ASSERT(flags & (FDB_READ|FDB_WRITE));
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate fdb = kmem_cache_alloc(fdb_cache, KM_SLEEP);
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate fdb_prepare(fdb);
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate fdb->fd_type = FDB_PAGEIO;
1077c478bd9Sstevel@tonic-gate fdb->fd_len = len;
1087c478bd9Sstevel@tonic-gate fdb->fd_state = flags;
1097c478bd9Sstevel@tonic-gate fdb->fd_pages = pp;
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate return (fdb);
1127c478bd9Sstevel@tonic-gate }
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate fdbuffer_t *
fdb_addr_create(caddr_t addr,size_t len,int flags,page_t ** pplist,struct proc * procp)1157c478bd9Sstevel@tonic-gate fdb_addr_create(
1167c478bd9Sstevel@tonic-gate caddr_t addr,
1177c478bd9Sstevel@tonic-gate size_t len,
1187c478bd9Sstevel@tonic-gate int flags,
1197c478bd9Sstevel@tonic-gate page_t **pplist,
1207c478bd9Sstevel@tonic-gate struct proc *procp)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate fdbuffer_t *fdb;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE,
1257c478bd9Sstevel@tonic-gate "?fdb_addr_create: addr: %p len: %lux flags: %x",
1267c478bd9Sstevel@tonic-gate (void *)addr, len, flags));
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate ASSERT(flags & (FDB_READ|FDB_WRITE));
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate fdb = kmem_cache_alloc(fdb_cache, KM_SLEEP);
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate fdb_prepare(fdb);
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate fdb->fd_type = FDB_VADDR;
1357c478bd9Sstevel@tonic-gate fdb->fd_len = len;
1367c478bd9Sstevel@tonic-gate fdb->fd_state = flags;
1377c478bd9Sstevel@tonic-gate fdb->fd_addr = addr;
1387c478bd9Sstevel@tonic-gate fdb->fd_shadow = pplist;
1397c478bd9Sstevel@tonic-gate fdb->fd_procp = procp;
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate return (fdb);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate void
fdb_set_iofunc(fdbuffer_t * fdb,fdb_iodone_t iofunc,void * ioargp,int flag)1457c478bd9Sstevel@tonic-gate fdb_set_iofunc(fdbuffer_t *fdb, fdb_iodone_t iofunc, void *ioargp, int flag)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate ASSERT(fdb);
1487c478bd9Sstevel@tonic-gate ASSERT(iofunc);
1497c478bd9Sstevel@tonic-gate ASSERT((flag & ~FDB_ICALLBACK) == 0);
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate fdb->fd_iofunc = iofunc;
1527c478bd9Sstevel@tonic-gate fdb->fd_iargp = ioargp;
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate if (flag & FDB_ICALLBACK)
1577c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ICALLBACK;
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ASYNC;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate int
fdb_get_error(fdbuffer_t * fdb)1657c478bd9Sstevel@tonic-gate fdb_get_error(fdbuffer_t *fdb)
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate return (fdb->fd_err);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate void
fdb_free(fdbuffer_t * fdb)1717c478bd9Sstevel@tonic-gate fdb_free(fdbuffer_t *fdb)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate fdb_holes_t *fdh, *fdhp;
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_CREATE, (CE_NOTE, "?fdb_free: addr: %p flags: %x",
1767c478bd9Sstevel@tonic-gate (void *)fdb, fdb->fd_state));
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate ASSERT(fdb);
1797c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch == 0);
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate if (fdb->fd_state & FDB_ZEROHOLE) {
1827c478bd9Sstevel@tonic-gate fdb_zero_holes(fdb);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate for (fdh = fdb->fd_holes; fdh; ) {
1867c478bd9Sstevel@tonic-gate fdhp = fdh;
1877c478bd9Sstevel@tonic-gate fdh = fdh->next_hole;
1887c478bd9Sstevel@tonic-gate kmem_free(fdhp, sizeof (fdb_holes_t));
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp != NULL) {
1927c478bd9Sstevel@tonic-gate switch (fdb->fd_type) {
1937c478bd9Sstevel@tonic-gate case FDB_PAGEIO:
1947c478bd9Sstevel@tonic-gate pageio_done(fdb->fd_parentbp);
1957c478bd9Sstevel@tonic-gate break;
1967c478bd9Sstevel@tonic-gate case FDB_VADDR:
1977c478bd9Sstevel@tonic-gate kmem_free(fdb->fd_parentbp, sizeof (struct buf));
1987c478bd9Sstevel@tonic-gate break;
1997c478bd9Sstevel@tonic-gate default:
2007c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?fdb_free: Unknown fdb type.");
2017c478bd9Sstevel@tonic-gate break;
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate kmem_cache_free(fdb_cache, fdb);
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate * The offset should be from the begining of the buffer
2117c478bd9Sstevel@tonic-gate * it has nothing to do with file offset. This fact should be
2127c478bd9Sstevel@tonic-gate * reflected in the caller of this routine.
2137c478bd9Sstevel@tonic-gate */
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate void
fdb_add_hole(fdbuffer_t * fdb,u_offset_t off,size_t len)2167c478bd9Sstevel@tonic-gate fdb_add_hole(fdbuffer_t *fdb, u_offset_t off, size_t len)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate fdb_holes_t *this_hole;
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate ASSERT(fdb);
2217c478bd9Sstevel@tonic-gate ASSERT(off < fdb->fd_len);
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE, "?fdb_add_hole: off %llx len %lx",
2247c478bd9Sstevel@tonic-gate off, len));
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate this_hole = kmem_alloc(sizeof (fdb_holes_t), KM_SLEEP);
2277c478bd9Sstevel@tonic-gate this_hole->off = off;
2287c478bd9Sstevel@tonic-gate this_hole->len = len;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate if (fdb->fd_holes == NULL || off < fdb->fd_holes->off) {
2317c478bd9Sstevel@tonic-gate this_hole->next_hole = fdb->fd_holes;
2327c478bd9Sstevel@tonic-gate fdb->fd_holes = this_hole;
2337c478bd9Sstevel@tonic-gate } else {
2347c478bd9Sstevel@tonic-gate fdb_holes_t *fdhp = fdb->fd_holes;
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate while (fdhp->next_hole && off > fdhp->next_hole->off)
2377c478bd9Sstevel@tonic-gate fdhp = fdhp->next_hole;
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate this_hole->next_hole = fdhp->next_hole;
2407c478bd9Sstevel@tonic-gate fdhp->next_hole = this_hole;
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate fdb->fd_iocount += len;
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate fdb_holes_t *
fdb_get_holes(fdbuffer_t * fdb)2517c478bd9Sstevel@tonic-gate fdb_get_holes(fdbuffer_t *fdb)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate ASSERT(fdb);
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate if (fdb->fd_state & FDB_ZEROHOLE) {
2567c478bd9Sstevel@tonic-gate fdb_zero_holes(fdb);
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate return (fdb->fd_holes);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate * Note that offsets refer to offsets from the begining of the buffer
2647c478bd9Sstevel@tonic-gate * and as such the memory should be cleared accordingly.
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate static void
fdb_zero_holes(fdbuffer_t * fdb)2687c478bd9Sstevel@tonic-gate fdb_zero_holes(fdbuffer_t *fdb)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate fdb_holes_t *fdh = fdb->fd_holes;
2717c478bd9Sstevel@tonic-gate page_t *pp;
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate ASSERT(fdb);
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate if (!fdh)
2767c478bd9Sstevel@tonic-gate return;
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate switch (fdb->fd_type) {
2797c478bd9Sstevel@tonic-gate case FDB_PAGEIO:
2807c478bd9Sstevel@tonic-gate pp = fdb->fd_pages;
2817c478bd9Sstevel@tonic-gate while (fdh) {
2827c478bd9Sstevel@tonic-gate fdb_holes_t *pfdh = fdh;
2837c478bd9Sstevel@tonic-gate size_t l = fdh->len;
2847c478bd9Sstevel@tonic-gate u_offset_t o = fdh->off;
2857c478bd9Sstevel@tonic-gate ASSERT(pp);
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate do {
2887c478bd9Sstevel@tonic-gate int zerolen;
2897c478bd9Sstevel@tonic-gate ASSERT(o >= pp->p_offset);
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate * This offset is wrong since
2937c478bd9Sstevel@tonic-gate * the offset passed from the pages
2947c478bd9Sstevel@tonic-gate * perspective starts at some virtual
2957c478bd9Sstevel@tonic-gate * address but the hole is relative
2967c478bd9Sstevel@tonic-gate * to the beginning of the fdbuffer.
2977c478bd9Sstevel@tonic-gate */
2987c478bd9Sstevel@tonic-gate if (o >= pp->p_offset + PAGESIZE)
2997c478bd9Sstevel@tonic-gate continue;
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate zerolen = min(PAGESIZE, l);
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate ASSERT(zerolen > 0);
3047c478bd9Sstevel@tonic-gate ASSERT(zerolen <= PAGESIZE);
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate pagezero(pp, ((uintptr_t)o & PAGEOFFSET),
3077c478bd9Sstevel@tonic-gate zerolen);
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate l -= zerolen;
3107c478bd9Sstevel@tonic-gate o += zerolen;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate if (l == 0)
3137c478bd9Sstevel@tonic-gate break;
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate } while (pp = page_list_next(pp));
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate if (!pp)
3187c478bd9Sstevel@tonic-gate break;
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate fdh = fdh->next_hole;
3217c478bd9Sstevel@tonic-gate kmem_free(pfdh, sizeof (fdb_holes_t));
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate break;
3247c478bd9Sstevel@tonic-gate case FDB_VADDR:
3257c478bd9Sstevel@tonic-gate while (fdh) {
3267c478bd9Sstevel@tonic-gate fdb_holes_t *pfdh = fdh;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate bzero(fdb->fd_addr + fdh->off, fdh->len);
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate fdh = fdh->next_hole;
3317c478bd9Sstevel@tonic-gate kmem_free(pfdh, sizeof (fdb_holes_t));
3327c478bd9Sstevel@tonic-gate }
333a9f62b1aSToomas Soome break;
3347c478bd9Sstevel@tonic-gate default:
3357c478bd9Sstevel@tonic-gate panic("fdb_zero_holes: Unknown fdb type.");
3367c478bd9Sstevel@tonic-gate break;
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate buf_t *
fdb_iosetup(fdbuffer_t * fdb,u_offset_t off,size_t len,struct vnode * vp,int b_flags)3427c478bd9Sstevel@tonic-gate fdb_iosetup(fdbuffer_t *fdb, u_offset_t off, size_t len, struct vnode *vp,
3437c478bd9Sstevel@tonic-gate int b_flags)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate buf_t *bp;
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE,
3487c478bd9Sstevel@tonic-gate "?fdb_iosetup: off: %llx len: %lux fdb: len: %lux flags: %x",
3497c478bd9Sstevel@tonic-gate off, len, fdb->fd_len, fdb->fd_state));
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate ASSERT(fdb);
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate ASSERT(((b_flags & B_READ) && (fdb->fd_state & FDB_READ)) ||
3567c478bd9Sstevel@tonic-gate ((b_flags & B_WRITE) && (fdb->fd_state & FDB_WRITE)));
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate * The fdb can be used either in sync or async mode, if the
3597c478bd9Sstevel@tonic-gate * buffer has not been used it may be used in either mode, but
3607c478bd9Sstevel@tonic-gate * once you have started to use the buf in either mode all
3617c478bd9Sstevel@tonic-gate * subsequent i/o requests must take place the same way.
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate ASSERT(((b_flags & B_ASYNC) &&
3657c478bd9Sstevel@tonic-gate ((fdb->fd_state & FDB_ASYNC) || !(fdb->fd_state & FDB_SYNC))) ||
3667c478bd9Sstevel@tonic-gate (!(b_flags & B_ASYNC) &&
3677c478bd9Sstevel@tonic-gate ((fdb->fd_state & FDB_SYNC) || !(fdb->fd_state & FDB_ASYNC))));
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate fdb->fd_state |= b_flags & B_ASYNC ? FDB_ASYNC : FDB_SYNC;
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate fdb->fd_iodispatch++;
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate ASSERT((fdb->fd_state & FDB_ASYNC && fdb->fd_iofunc != NULL) ||
3757c478bd9Sstevel@tonic-gate fdb->fd_state & FDB_SYNC);
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate ASSERT((len & (DEV_BSIZE - 1)) == 0);
3807c478bd9Sstevel@tonic-gate ASSERT(off+len <= fdb->fd_len);
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate switch (fdb->fd_type) {
3837c478bd9Sstevel@tonic-gate case FDB_PAGEIO:
3847c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp == NULL) {
3857c478bd9Sstevel@tonic-gate bp = pageio_setup(fdb->fd_pages, len, vp, b_flags);
3867c478bd9Sstevel@tonic-gate fdb->fd_parentbp = bp;
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate break;
3897c478bd9Sstevel@tonic-gate case FDB_VADDR:
3907c478bd9Sstevel@tonic-gate if (fdb->fd_parentbp == NULL) {
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate bp = kmem_alloc(sizeof (buf_t), KM_SLEEP);
3937c478bd9Sstevel@tonic-gate bioinit(bp);
3947c478bd9Sstevel@tonic-gate bp->b_error = 0;
3957c478bd9Sstevel@tonic-gate bp->b_proc = fdb->fd_procp;
3967c478bd9Sstevel@tonic-gate bp->b_flags = b_flags | B_BUSY | B_PHYS;
3977c478bd9Sstevel@tonic-gate bp->b_bcount = len;
3987c478bd9Sstevel@tonic-gate bp->b_un.b_addr = fdb->fd_addr;
3997c478bd9Sstevel@tonic-gate bp->b_shadow = fdb->fd_shadow;
4007c478bd9Sstevel@tonic-gate if (fdb->fd_shadow != NULL)
4017c478bd9Sstevel@tonic-gate bp->b_flags |= B_SHADOW;
4027c478bd9Sstevel@tonic-gate fdb->fd_parentbp = bp;
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate break;
4057c478bd9Sstevel@tonic-gate default:
4067c478bd9Sstevel@tonic-gate panic("fdb_iosetup: Unsupported fdb type.");
4077c478bd9Sstevel@tonic-gate break;
4087c478bd9Sstevel@tonic-gate };
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate bp = bioclone(fdb->fd_parentbp, off, len, 0, 0,
411*b94c9724SToomas Soome (b_flags & B_ASYNC) ? fdb_iodone : NULL,
4127c478bd9Sstevel@tonic-gate NULL, KM_SLEEP);
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate bp->b_forw = (struct buf *)fdb;
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate if (b_flags & B_ASYNC)
4177c478bd9Sstevel@tonic-gate bp->b_flags |= B_ASYNC;
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate return (bp);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate size_t
fdb_get_iolen(fdbuffer_t * fdb)4237c478bd9Sstevel@tonic-gate fdb_get_iolen(fdbuffer_t *fdb)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate ASSERT(fdb);
4267c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch == 0);
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate return (fdb->fd_iocount - fdb->fd_resid);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate void
fdb_ioerrdone(fdbuffer_t * fdb,int error)4327c478bd9Sstevel@tonic-gate fdb_ioerrdone(fdbuffer_t *fdb, int error)
4337c478bd9Sstevel@tonic-gate {
4347c478bd9Sstevel@tonic-gate ASSERT(fdb);
4357c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_state & FDB_ASYNC);
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE,
4387c478bd9Sstevel@tonic-gate "?fdb_ioerrdone: fdb: len: %lux flags: %x error: %d",
4397c478bd9Sstevel@tonic-gate fdb->fd_len, fdb->fd_state, error));
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate fdb->fd_err = error;
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate if (error)
4467c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_ERROR;
4477c478bd9Sstevel@tonic-gate else
4487c478bd9Sstevel@tonic-gate fdb->fd_state |= FDB_DONE;
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate /*
4517c478bd9Sstevel@tonic-gate * If there is outstanding i/o return wainting for i/o's to complete.
4527c478bd9Sstevel@tonic-gate */
4537c478bd9Sstevel@tonic-gate if (fdb->fd_iodispatch > 0) {
4547c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
4557c478bd9Sstevel@tonic-gate return;
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
4597c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, NULL);
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate
462*b94c9724SToomas Soome int
fdb_iodone(buf_t * bp)4637c478bd9Sstevel@tonic-gate fdb_iodone(buf_t *bp)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate fdbuffer_t *fdb = (fdbuffer_t *)bp->b_forw;
4667c478bd9Sstevel@tonic-gate int error, isasync;
4677c478bd9Sstevel@tonic-gate int icallback;
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate ASSERT(fdb);
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate DEBUGF(FDB_D_IO, (CE_NOTE,
4727c478bd9Sstevel@tonic-gate "?fdb_iodone: fdb: len: %lux flags: %x error: %d",
4737c478bd9Sstevel@tonic-gate fdb->fd_len, fdb->fd_state, geterror(bp)));
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate if (bp->b_flags & B_REMAPPED)
4767c478bd9Sstevel@tonic-gate bp_mapout(bp);
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate mutex_enter(&fdb->fd_mutex);
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate icallback = fdb->fd_state & FDB_ICALLBACK;
4817c478bd9Sstevel@tonic-gate isasync = fdb->fd_state & FDB_ASYNC;
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate ASSERT(fdb->fd_iodispatch > 0);
4847c478bd9Sstevel@tonic-gate fdb->fd_iodispatch--;
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate if (error = geterror(bp)) {
4877c478bd9Sstevel@tonic-gate fdb->fd_err = error;
4887c478bd9Sstevel@tonic-gate if (bp->b_resid)
4897c478bd9Sstevel@tonic-gate fdb->fd_resid += bp->b_resid;
4907c478bd9Sstevel@tonic-gate else
4917c478bd9Sstevel@tonic-gate fdb->fd_resid += bp->b_bcount;
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate fdb->fd_iocount += bp->b_bcount;
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate /*
4977c478bd9Sstevel@tonic-gate * ioack collects the total amount of i/o accounted for
4987c478bd9Sstevel@tonic-gate * this includes:
4997c478bd9Sstevel@tonic-gate *
5007c478bd9Sstevel@tonic-gate * - i/o completed
5017c478bd9Sstevel@tonic-gate * - i/o attempted but not completed,
5027c478bd9Sstevel@tonic-gate * - i/o not done due to holes.
5037c478bd9Sstevel@tonic-gate *
5047c478bd9Sstevel@tonic-gate * Once the entire i/o ranges has been accounted for we'll
5057c478bd9Sstevel@tonic-gate * call the async function associated with the fdb.
5067c478bd9Sstevel@tonic-gate *
5077c478bd9Sstevel@tonic-gate */
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate if ((fdb->fd_iodispatch == 0) &&
5107c478bd9Sstevel@tonic-gate (fdb->fd_state & (FDB_ERROR|FDB_DONE))) {
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate if (isasync || icallback) {
5157c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, bp);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate } else {
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate mutex_exit(&fdb->fd_mutex);
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate if (icallback) {
5237c478bd9Sstevel@tonic-gate fdb->fd_iofunc(fdb, fdb->fd_iargp, bp);
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate }
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate freerbuf(bp);
528*b94c9724SToomas Soome return (0);
5297c478bd9Sstevel@tonic-gate }
530