1*39019Smckusick /* 2*39019Smckusick * Copyright (c) 1989 The Regents of the University of California. 3*39019Smckusick * All rights reserved. 4*39019Smckusick * 5*39019Smckusick * Redistribution and use in source and binary forms are permitted 6*39019Smckusick * provided that the above copyright notice and this paragraph are 7*39019Smckusick * duplicated in all such forms and that any documentation, 8*39019Smckusick * advertising materials, and other materials related to such 9*39019Smckusick * distribution and use acknowledge that the software was developed 10*39019Smckusick * by the University of California, Berkeley. The name of the 11*39019Smckusick * University may not be used to endorse or promote products derived 12*39019Smckusick * from this software without specific prior written permission. 13*39019Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*39019Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*39019Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*39019Smckusick * 17*39019Smckusick * @(#)mfs_vnops.c 7.1 (Berkeley) 09/05/89 18*39019Smckusick */ 19*39019Smckusick 20*39019Smckusick #include "param.h" 21*39019Smckusick #include "time.h" 22*39019Smckusick #include "proc.h" 23*39019Smckusick #include "buf.h" 24*39019Smckusick #include "vmmac.h" 25*39019Smckusick #include "errno.h" 26*39019Smckusick #include "map.h" 27*39019Smckusick #include "vnode.h" 28*39019Smckusick #include "../ufs/inode.h" 29*39019Smckusick #include "../ufs/mfsiom.h" 30*39019Smckusick #include "../machine/vmparam.h" 31*39019Smckusick #include "../machine/pte.h" 32*39019Smckusick #include "../machine/mtpr.h" 33*39019Smckusick 34*39019Smckusick int mfs_running; /* 1 => daemon has started running */ 35*39019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 36*39019Smckusick struct map mfsmap[MFS_MAPSIZE]; 37*39019Smckusick extern char mfsiobuf[]; 38*39019Smckusick 39*39019Smckusick /* 40*39019Smckusick * mfs vnode operations. 41*39019Smckusick */ 42*39019Smckusick int mfs_open(), 43*39019Smckusick mfs_strategy(), 44*39019Smckusick mfs_ioctl(), 45*39019Smckusick mfs_close(), 46*39019Smckusick ufs_inactive(), 47*39019Smckusick mfs_badop(), 48*39019Smckusick mfs_nullop(); 49*39019Smckusick 50*39019Smckusick struct vnodeops mfs_vnodeops = { 51*39019Smckusick mfs_badop, 52*39019Smckusick mfs_badop, 53*39019Smckusick mfs_badop, 54*39019Smckusick mfs_open, 55*39019Smckusick mfs_close, 56*39019Smckusick mfs_badop, 57*39019Smckusick mfs_badop, 58*39019Smckusick mfs_badop, 59*39019Smckusick mfs_badop, 60*39019Smckusick mfs_badop, 61*39019Smckusick mfs_ioctl, 62*39019Smckusick mfs_badop, 63*39019Smckusick mfs_badop, 64*39019Smckusick mfs_badop, 65*39019Smckusick mfs_badop, 66*39019Smckusick mfs_badop, 67*39019Smckusick mfs_badop, 68*39019Smckusick mfs_badop, 69*39019Smckusick mfs_badop, 70*39019Smckusick mfs_badop, 71*39019Smckusick mfs_badop, 72*39019Smckusick mfs_badop, 73*39019Smckusick mfs_badop, 74*39019Smckusick mfs_badop, 75*39019Smckusick ufs_inactive, 76*39019Smckusick mfs_badop, 77*39019Smckusick mfs_badop, 78*39019Smckusick mfs_badop, 79*39019Smckusick mfs_strategy, 80*39019Smckusick }; 81*39019Smckusick 82*39019Smckusick /* 83*39019Smckusick * Vnode Operations. 84*39019Smckusick * 85*39019Smckusick * Open called to allow memory filesystem to initialize and 86*39019Smckusick * validate before actual IO. Nothing to do here as the 87*39019Smckusick * filesystem is ready to go in the process address space. 88*39019Smckusick */ 89*39019Smckusick /* ARGSUSED */ 90*39019Smckusick mfs_open(vp, mode, cred) 91*39019Smckusick register struct vnode *vp; 92*39019Smckusick int mode; 93*39019Smckusick struct ucred *cred; 94*39019Smckusick { 95*39019Smckusick 96*39019Smckusick if (vp->v_type != VBLK) { 97*39019Smckusick panic("mfs_ioctl not VBLK"); 98*39019Smckusick /* NOTREACHED */ 99*39019Smckusick } 100*39019Smckusick return (0); 101*39019Smckusick } 102*39019Smckusick 103*39019Smckusick /* 104*39019Smckusick * Ioctl operation. 105*39019Smckusick */ 106*39019Smckusick /* ARGSUSED */ 107*39019Smckusick mfs_ioctl(vp, com, data, fflag, cred) 108*39019Smckusick struct vnode *vp; 109*39019Smckusick int com; 110*39019Smckusick caddr_t data; 111*39019Smckusick int fflag; 112*39019Smckusick struct ucred *cred; 113*39019Smckusick { 114*39019Smckusick 115*39019Smckusick return (-1); 116*39019Smckusick } 117*39019Smckusick 118*39019Smckusick /* 119*39019Smckusick * Pass I/O requests to the memory filesystem process. 120*39019Smckusick */ 121*39019Smckusick mfs_strategy(bp) 122*39019Smckusick register struct buf *bp; 123*39019Smckusick { 124*39019Smckusick register struct inode *ip = VTOI(bp->b_vp); 125*39019Smckusick int error; 126*39019Smckusick 127*39019Smckusick ILOCK(ip); 128*39019Smckusick if (!mfs_running) { 129*39019Smckusick mfs_doio(bp, (caddr_t)ip->i_diroff); 130*39019Smckusick } else { 131*39019Smckusick ip->i_spare[0] = (long)bp; 132*39019Smckusick wakeup((caddr_t)bp->b_vp); 133*39019Smckusick } 134*39019Smckusick error = biowait(bp); 135*39019Smckusick IUNLOCK(ip); 136*39019Smckusick return (error); 137*39019Smckusick } 138*39019Smckusick 139*39019Smckusick /* 140*39019Smckusick * Memory file system I/O. 141*39019Smckusick * 142*39019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 143*39019Smckusick * doing the copies to or from the memfs process. If doing physio 144*39019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 145*39019Smckusick * address space. 146*39019Smckusick */ 147*39019Smckusick mfs_doio(bp, base) 148*39019Smckusick register struct buf *bp; 149*39019Smckusick caddr_t base; 150*39019Smckusick { 151*39019Smckusick register struct pte *pte, *ppte; 152*39019Smckusick register caddr_t vaddr; 153*39019Smckusick int off, npf, npf2, reg; 154*39019Smckusick caddr_t kernaddr, offset; 155*39019Smckusick 156*39019Smckusick /* 157*39019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 158*39019Smckusick * the Mfsiomap pte's. 159*39019Smckusick */ 160*39019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 161*39019Smckusick kernaddr = bp->b_un.b_addr; 162*39019Smckusick } else { 163*39019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 164*39019Smckusick panic("swap on memfs?"); 165*39019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 166*39019Smckusick npf = btoc(bp->b_bcount + off); 167*39019Smckusick /* 168*39019Smckusick * Get some mapping page table entries 169*39019Smckusick */ 170*39019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 171*39019Smckusick mfsmap_want++; 172*39019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 173*39019Smckusick } 174*39019Smckusick reg--; 175*39019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 176*39019Smckusick /* 177*39019Smckusick * Do vmaccess() but with the Mfsiomap page table. 178*39019Smckusick */ 179*39019Smckusick ppte = &Mfsiomap[reg]; 180*39019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 181*39019Smckusick kernaddr = vaddr + off; 182*39019Smckusick for (npf2 = npf; npf2; npf2--) { 183*39019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 184*39019Smckusick (int)(PG_V|PG_KW)); 185*39019Smckusick #if defined(tahoe) 186*39019Smckusick if ((bp->b_flags & B_READ) == 0) 187*39019Smckusick mtpr(P1DC, vaddr); 188*39019Smckusick #endif 189*39019Smckusick ppte++; 190*39019Smckusick pte++; 191*39019Smckusick vaddr += NBPG; 192*39019Smckusick } 193*39019Smckusick } 194*39019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 195*39019Smckusick if (bp->b_flags & B_READ) 196*39019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 197*39019Smckusick else 198*39019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 199*39019Smckusick if (bp->b_error) 200*39019Smckusick bp->b_flags |= B_ERROR; 201*39019Smckusick /* 202*39019Smckusick * Release pte's used by physical I/O. 203*39019Smckusick */ 204*39019Smckusick if (bp->b_flags & B_PHYS) { 205*39019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 206*39019Smckusick if (mfsmap_want) { 207*39019Smckusick mfsmap_want = 0; 208*39019Smckusick wakeup((caddr_t)&mfsmap_want); 209*39019Smckusick } 210*39019Smckusick } 211*39019Smckusick biodone(bp); 212*39019Smckusick } 213*39019Smckusick 214*39019Smckusick /* 215*39019Smckusick * Memory filesystem close routine 216*39019Smckusick */ 217*39019Smckusick /* ARGSUSED */ 218*39019Smckusick mfs_close(vp, flag, cred) 219*39019Smckusick register struct vnode *vp; 220*39019Smckusick int flag; 221*39019Smckusick struct ucred *cred; 222*39019Smckusick { 223*39019Smckusick register struct inode *ip = VTOI(vp); 224*39019Smckusick 225*39019Smckusick /* 226*39019Smckusick * On last close of a memory filesystem 227*39019Smckusick * we must invalidate any in core blocks, so that 228*39019Smckusick * we can, free up its vnode. 229*39019Smckusick */ 230*39019Smckusick bflush(vp->v_mount); 231*39019Smckusick if (binval(vp->v_mount)) 232*39019Smckusick return (0); 233*39019Smckusick /* 234*39019Smckusick * We don't want to really close the device if it is still 235*39019Smckusick * in use. Since every use (buffer, inode, swap, cmap) 236*39019Smckusick * holds a reference to the vnode, and because we ensure 237*39019Smckusick * that there cannot be more than one vnode per device, 238*39019Smckusick * we need only check that we are down to the last 239*39019Smckusick * reference before closing. 240*39019Smckusick */ 241*39019Smckusick if (vp->v_count > 1) { 242*39019Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_count); 243*39019Smckusick return (0); 244*39019Smckusick } 245*39019Smckusick /* 246*39019Smckusick * Send a request to the filesystem server to exit. 247*39019Smckusick */ 248*39019Smckusick ILOCK(ip); 249*39019Smckusick ip->i_spare[0] = 0; 250*39019Smckusick wakeup((caddr_t)vp); 251*39019Smckusick IUNLOCK(ip); 252*39019Smckusick return (0); 253*39019Smckusick } 254*39019Smckusick 255*39019Smckusick /* 256*39019Smckusick * Block device bad operation 257*39019Smckusick */ 258*39019Smckusick mfs_badop() 259*39019Smckusick { 260*39019Smckusick 261*39019Smckusick printf("mfs_badop called\n"); 262*39019Smckusick return (ENXIO); 263*39019Smckusick } 264*39019Smckusick 265*39019Smckusick /* 266*39019Smckusick * Block device null operation 267*39019Smckusick */ 268*39019Smckusick mfs_nullop() 269*39019Smckusick { 270*39019Smckusick 271*39019Smckusick return (0); 272*39019Smckusick } 273*39019Smckusick 274*39019Smckusick /* 275*39019Smckusick * Memory based filesystem initialization. 276*39019Smckusick */ 277*39019Smckusick mfs_init() 278*39019Smckusick { 279*39019Smckusick 280*39019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 281*39019Smckusick } 282