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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 28*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/fbuf.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 46*7c478bd9Sstevel@tonic-gate #include <vm/hat.h> 47*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 48*7c478bd9Sstevel@tonic-gate #include <vm/seg.h> 49*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 50*7c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 51*7c478bd9Sstevel@tonic-gate #include <vm/seg_kpm.h> 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* 55*7c478bd9Sstevel@tonic-gate * Pseudo-bio routines which use a segmap mapping to address file data. 56*7c478bd9Sstevel@tonic-gate */ 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * Return a pointer to locked kernel virtual address for 60*7c478bd9Sstevel@tonic-gate * the given <vp, off> for len bytes. It is not allowed to 61*7c478bd9Sstevel@tonic-gate * have the offset cross a MAXBSIZE boundary over len bytes. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate int 64*7c478bd9Sstevel@tonic-gate fbread(vnode_t *vp, offset_t off, uint_t len, enum seg_rw rw, 65*7c478bd9Sstevel@tonic-gate struct fbuf **fbpp) 66*7c478bd9Sstevel@tonic-gate { 67*7c478bd9Sstevel@tonic-gate caddr_t addr; 68*7c478bd9Sstevel@tonic-gate ulong_t o; 69*7c478bd9Sstevel@tonic-gate struct fbuf *fbp; 70*7c478bd9Sstevel@tonic-gate faultcode_t err; 71*7c478bd9Sstevel@tonic-gate caddr_t raddr; 72*7c478bd9Sstevel@tonic-gate uint_t rsize; 73*7c478bd9Sstevel@tonic-gate uintptr_t pgoff = PAGEOFFSET; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate o = (ulong_t)(off & (offset_t)MAXBOFFSET); 76*7c478bd9Sstevel@tonic-gate if (o + len > MAXBSIZE) 77*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "fbread"); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate if (segmap_kpm) { 80*7c478bd9Sstevel@tonic-gate addr = segmap_getmapflt(segkmap, vp, off & (offset_t)MAXBMASK, 81*7c478bd9Sstevel@tonic-gate MAXBSIZE, SM_LOCKPROTO, rw); 82*7c478bd9Sstevel@tonic-gate } else { 83*7c478bd9Sstevel@tonic-gate addr = segmap_getmapflt(segkmap, vp, 84*7c478bd9Sstevel@tonic-gate off & (offset_t)MAXBMASK, MAXBSIZE, 0, rw); 85*7c478bd9Sstevel@tonic-gate } 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate raddr = (caddr_t)((uintptr_t)(addr + o) & ~pgoff); 88*7c478bd9Sstevel@tonic-gate rsize = (((uintptr_t)(addr + o) + len + pgoff) & ~pgoff) - 89*7c478bd9Sstevel@tonic-gate (uintptr_t)raddr; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate err = segmap_fault(kas.a_hat, segkmap, raddr, rsize, F_SOFTLOCK, rw); 92*7c478bd9Sstevel@tonic-gate if (err) { 93*7c478bd9Sstevel@tonic-gate (void) segmap_release(segkmap, addr, 0); 94*7c478bd9Sstevel@tonic-gate if (FC_CODE(err) == FC_OBJERR) 95*7c478bd9Sstevel@tonic-gate return (FC_ERRNO(err)); 96*7c478bd9Sstevel@tonic-gate else 97*7c478bd9Sstevel@tonic-gate return (EIO); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate *fbpp = fbp = kmem_alloc(sizeof (struct fbuf), KM_SLEEP); 101*7c478bd9Sstevel@tonic-gate fbp->fb_addr = addr + o; 102*7c478bd9Sstevel@tonic-gate fbp->fb_count = len; 103*7c478bd9Sstevel@tonic-gate return (0); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * Similar to fbread() but we call segmap_pagecreate instead of using 108*7c478bd9Sstevel@tonic-gate * segmap_fault for SOFTLOCK to create the pages without using VOP_GETPAGE 109*7c478bd9Sstevel@tonic-gate * and then we zero up to the length rounded to a page boundary. 110*7c478bd9Sstevel@tonic-gate * XXX - this won't work right when bsize < PAGESIZE!!! 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate void 113*7c478bd9Sstevel@tonic-gate fbzero(vnode_t *vp, offset_t off, uint_t len, struct fbuf **fbpp) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate caddr_t addr; 116*7c478bd9Sstevel@tonic-gate ulong_t o, zlen; 117*7c478bd9Sstevel@tonic-gate struct fbuf *fbp; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate o = (ulong_t)(off & MAXBOFFSET); 120*7c478bd9Sstevel@tonic-gate if (o + len > MAXBSIZE) 121*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "fbzero: Bad offset/length"); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate if (segmap_kpm) { 124*7c478bd9Sstevel@tonic-gate addr = segmap_getmapflt(segkmap, vp, off & (offset_t)MAXBMASK, 125*7c478bd9Sstevel@tonic-gate MAXBSIZE, SM_PAGECREATE, S_WRITE) + o; 126*7c478bd9Sstevel@tonic-gate } else { 127*7c478bd9Sstevel@tonic-gate addr = segmap_getmap(segkmap, vp, off & (offset_t)MAXBMASK) + o; 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate *fbpp = fbp = kmem_alloc(sizeof (struct fbuf), KM_SLEEP); 131*7c478bd9Sstevel@tonic-gate fbp->fb_addr = addr; 132*7c478bd9Sstevel@tonic-gate fbp->fb_count = len; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate (void) segmap_pagecreate(segkmap, addr, len, 1); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate * Now we zero all the memory in the mapping we are interested in. 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate zlen = (caddr_t)ptob(btopr((uintptr_t)(len + addr))) - addr; 140*7c478bd9Sstevel@tonic-gate if (zlen < len || (o + zlen > MAXBSIZE)) 141*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "fbzero: Bad zlen"); 142*7c478bd9Sstevel@tonic-gate bzero(addr, zlen); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * FBCOMMON() is the common code for fbrelse, fbwrite and variants thereof: 147*7c478bd9Sstevel@tonic-gate * 148*7c478bd9Sstevel@tonic-gate * fbrelse() release fbp 149*7c478bd9Sstevel@tonic-gate * fbwrite() direct write 150*7c478bd9Sstevel@tonic-gate * fbdwrite() delayed write 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate #define FBCOMMON(fbp, rw, flags, howtoreturn) \ 153*7c478bd9Sstevel@tonic-gate { \ 154*7c478bd9Sstevel@tonic-gate caddr_t addr; \ 155*7c478bd9Sstevel@tonic-gate size_t size; \ 156*7c478bd9Sstevel@tonic-gate uintptr_t pgoff = PAGEOFFSET; \ 157*7c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)fbp->fb_addr & ~pgoff); \ 158*7c478bd9Sstevel@tonic-gate size = ((fbp->fb_addr - addr) + fbp->fb_count + pgoff) & ~pgoff; \ 159*7c478bd9Sstevel@tonic-gate (void) segmap_fault(kas.a_hat, segkmap, addr, size, F_SOFTUNLOCK, rw); \ 160*7c478bd9Sstevel@tonic-gate addr = (caddr_t)((uintptr_t)fbp->fb_addr & MAXBMASK); \ 161*7c478bd9Sstevel@tonic-gate kmem_free(fbp, sizeof (struct fbuf)); \ 162*7c478bd9Sstevel@tonic-gate howtoreturn(segmap_release(segkmap, addr, flags)); \ 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate void 166*7c478bd9Sstevel@tonic-gate fbrelse(struct fbuf *fbp, enum seg_rw rw) 167*7c478bd9Sstevel@tonic-gate { 168*7c478bd9Sstevel@tonic-gate FBCOMMON(fbp, rw, 0, (void)) 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate int 172*7c478bd9Sstevel@tonic-gate fbwrite(struct fbuf *fbp) 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate FBCOMMON(fbp, S_WRITE, SM_WRITE, return) 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate int 178*7c478bd9Sstevel@tonic-gate fbdwrite(struct fbuf *fbp) 179*7c478bd9Sstevel@tonic-gate { 180*7c478bd9Sstevel@tonic-gate FBCOMMON(fbp, S_WRITE, 0, return) 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate /* 184*7c478bd9Sstevel@tonic-gate * Perform a synchronous indirect write of the given block number 185*7c478bd9Sstevel@tonic-gate * on the given device, using the given fbuf. Upon return the fbp 186*7c478bd9Sstevel@tonic-gate * is invalid. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate int 189*7c478bd9Sstevel@tonic-gate fbiwrite(struct fbuf *fbp, vnode_t *devvp, daddr_t bn, int bsize) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate struct buf *bp; 192*7c478bd9Sstevel@tonic-gate int error, fberror; 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * Allocate a temp bp using pageio_setup, but then use it 196*7c478bd9Sstevel@tonic-gate * for physio to the area mapped by fbuf which is currently 197*7c478bd9Sstevel@tonic-gate * all locked down in place. 198*7c478bd9Sstevel@tonic-gate * 199*7c478bd9Sstevel@tonic-gate * XXX - need to have a generalized bp header facility 200*7c478bd9Sstevel@tonic-gate * which we build up pageio_setup on top of. Other places 201*7c478bd9Sstevel@tonic-gate * (like here and in device drivers for the raw I/O case) 202*7c478bd9Sstevel@tonic-gate * could then use these new facilities in a more straight 203*7c478bd9Sstevel@tonic-gate * forward fashion instead of playing all these games. 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate bp = pageio_setup((struct page *)NULL, fbp->fb_count, devvp, B_WRITE); 206*7c478bd9Sstevel@tonic-gate bp->b_flags &= ~B_PAGEIO; /* XXX */ 207*7c478bd9Sstevel@tonic-gate bp->b_un.b_addr = fbp->fb_addr; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate bp->b_blkno = bn * btod(bsize); 210*7c478bd9Sstevel@tonic-gate bp->b_dev = cmpdev(devvp->v_rdev); /* store in old dev format */ 211*7c478bd9Sstevel@tonic-gate bp->b_edev = devvp->v_rdev; 212*7c478bd9Sstevel@tonic-gate bp->b_proc = NULL; /* i.e. the kernel */ 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate (void) bdev_strategy(bp); 215*7c478bd9Sstevel@tonic-gate error = biowait(bp); 216*7c478bd9Sstevel@tonic-gate pageio_done(bp); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /*CSTYLED*/ 219*7c478bd9Sstevel@tonic-gate FBCOMMON(fbp, S_OTHER, 0, fberror = ) 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate return (error ? error : fberror); 222*7c478bd9Sstevel@tonic-gate } 223