139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 539019Smckusick * Redistribution and use in source and binary forms are permitted 639019Smckusick * provided that the above copyright notice and this paragraph are 739019Smckusick * duplicated in all such forms and that any documentation, 839019Smckusick * advertising materials, and other materials related to such 939019Smckusick * distribution and use acknowledge that the software was developed 1039019Smckusick * by the University of California, Berkeley. The name of the 1139019Smckusick * University may not be used to endorse or promote products derived 1239019Smckusick * from this software without specific prior written permission. 1339019Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1439019Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1539019Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1639019Smckusick * 17*39677Smckusick * @(#)mfs_vnops.c 7.9 (Berkeley) 11/30/89 1839019Smckusick */ 1939019Smckusick 2039019Smckusick #include "param.h" 2139019Smckusick #include "time.h" 2239357Smckusick #include "kernel.h" 2339019Smckusick #include "proc.h" 2439357Smckusick #include "user.h" 2539019Smckusick #include "buf.h" 2639019Smckusick #include "vmmac.h" 2739019Smckusick #include "errno.h" 2839019Smckusick #include "map.h" 2939019Smckusick #include "vnode.h" 3039389Smckusick #include "../ufs/mfsnode.h" 3139019Smckusick #include "../ufs/mfsiom.h" 3239456Smckusick #include "machine/vmparam.h" 3339456Smckusick #include "machine/pte.h" 3439456Smckusick #include "machine/mtpr.h" 3539019Smckusick 3639019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 3739019Smckusick struct map mfsmap[MFS_MAPSIZE]; 3839019Smckusick extern char mfsiobuf[]; 3939019Smckusick 4039019Smckusick /* 4139019Smckusick * mfs vnode operations. 4239019Smckusick */ 4339019Smckusick int mfs_open(), 4439019Smckusick mfs_strategy(), 4539019Smckusick mfs_ioctl(), 4639019Smckusick mfs_close(), 4739389Smckusick mfs_inactive(), 48*39677Smckusick mfs_print(), 4939019Smckusick mfs_badop(), 5039019Smckusick mfs_nullop(); 5139019Smckusick 5239019Smckusick struct vnodeops mfs_vnodeops = { 53*39677Smckusick mfs_badop, /* lookup */ 54*39677Smckusick mfs_badop, /* create */ 55*39677Smckusick mfs_badop, /* mknod */ 56*39677Smckusick mfs_open, /* open */ 57*39677Smckusick mfs_close, /* close */ 58*39677Smckusick mfs_badop, /* access */ 59*39677Smckusick mfs_badop, /* getattr */ 60*39677Smckusick mfs_badop, /* setattr */ 61*39677Smckusick mfs_badop, /* read */ 62*39677Smckusick mfs_badop, /* write */ 63*39677Smckusick mfs_ioctl, /* ioctl */ 64*39677Smckusick mfs_badop, /* select */ 65*39677Smckusick mfs_badop, /* mmap */ 66*39677Smckusick mfs_badop, /* fsync */ 67*39677Smckusick mfs_badop, /* seek */ 68*39677Smckusick mfs_badop, /* remove */ 69*39677Smckusick mfs_badop, /* link */ 70*39677Smckusick mfs_badop, /* rename */ 71*39677Smckusick mfs_badop, /* mkdir */ 72*39677Smckusick mfs_badop, /* rmdir */ 73*39677Smckusick mfs_badop, /* symlink */ 74*39677Smckusick mfs_badop, /* readdir */ 75*39677Smckusick mfs_badop, /* readlink */ 76*39677Smckusick mfs_badop, /* abortop */ 77*39677Smckusick mfs_inactive, /* inactive */ 78*39677Smckusick mfs_nullop, /* reclaim */ 79*39677Smckusick mfs_badop, /* lock */ 80*39677Smckusick mfs_badop, /* unlock */ 81*39677Smckusick mfs_badop, /* bmap */ 82*39677Smckusick mfs_strategy, /* strategy */ 83*39677Smckusick mfs_print, /* print */ 8439019Smckusick }; 8539019Smckusick 8639019Smckusick /* 8739019Smckusick * Vnode Operations. 8839019Smckusick * 8939019Smckusick * Open called to allow memory filesystem to initialize and 9039357Smckusick * validate before actual IO. Record our process identifier 9139357Smckusick * so we can tell when we are doing I/O to ourself. 9239019Smckusick */ 9339019Smckusick /* ARGSUSED */ 9439019Smckusick mfs_open(vp, mode, cred) 9539019Smckusick register struct vnode *vp; 9639019Smckusick int mode; 9739019Smckusick struct ucred *cred; 9839019Smckusick { 9939019Smckusick 10039019Smckusick if (vp->v_type != VBLK) { 10139019Smckusick panic("mfs_ioctl not VBLK"); 10239019Smckusick /* NOTREACHED */ 10339019Smckusick } 10439019Smckusick return (0); 10539019Smckusick } 10639019Smckusick 10739019Smckusick /* 10839019Smckusick * Ioctl operation. 10939019Smckusick */ 11039019Smckusick /* ARGSUSED */ 11139019Smckusick mfs_ioctl(vp, com, data, fflag, cred) 11239019Smckusick struct vnode *vp; 11339019Smckusick int com; 11439019Smckusick caddr_t data; 11539019Smckusick int fflag; 11639019Smckusick struct ucred *cred; 11739019Smckusick { 11839019Smckusick 11939019Smckusick return (-1); 12039019Smckusick } 12139019Smckusick 12239019Smckusick /* 12339019Smckusick * Pass I/O requests to the memory filesystem process. 12439019Smckusick */ 12539019Smckusick mfs_strategy(bp) 12639019Smckusick register struct buf *bp; 12739019Smckusick { 12839389Smckusick register struct mfsnode *mfsp = VTOMFS(bp->b_vp); 12939019Smckusick 13039389Smckusick if (mfsp->mfs_pid == u.u_procp->p_pid) { 13139389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 13239019Smckusick } else { 13339389Smckusick bp->av_forw = mfsp->mfs_buflist; 13439389Smckusick mfsp->mfs_buflist = bp; 13539019Smckusick wakeup((caddr_t)bp->b_vp); 13639019Smckusick } 13739357Smckusick return (0); 13839019Smckusick } 13939019Smckusick 14039019Smckusick /* 14139019Smckusick * Memory file system I/O. 14239019Smckusick * 14339019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 14439019Smckusick * doing the copies to or from the memfs process. If doing physio 14539019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 14639019Smckusick * address space. 14739019Smckusick */ 14839019Smckusick mfs_doio(bp, base) 14939019Smckusick register struct buf *bp; 15039019Smckusick caddr_t base; 15139019Smckusick { 15239019Smckusick register struct pte *pte, *ppte; 15339019Smckusick register caddr_t vaddr; 15439019Smckusick int off, npf, npf2, reg; 15539019Smckusick caddr_t kernaddr, offset; 15639019Smckusick 15739019Smckusick /* 15839019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 15939019Smckusick * the Mfsiomap pte's. 16039019Smckusick */ 16139019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 16239019Smckusick kernaddr = bp->b_un.b_addr; 16339019Smckusick } else { 16439019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 16539019Smckusick panic("swap on memfs?"); 16639019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 16739019Smckusick npf = btoc(bp->b_bcount + off); 16839019Smckusick /* 16939019Smckusick * Get some mapping page table entries 17039019Smckusick */ 17139019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 17239019Smckusick mfsmap_want++; 17339019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 17439019Smckusick } 17539019Smckusick reg--; 17639019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 17739019Smckusick /* 17839019Smckusick * Do vmaccess() but with the Mfsiomap page table. 17939019Smckusick */ 18039019Smckusick ppte = &Mfsiomap[reg]; 18139019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 18239019Smckusick kernaddr = vaddr + off; 18339019Smckusick for (npf2 = npf; npf2; npf2--) { 18439019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 18539019Smckusick (int)(PG_V|PG_KW)); 18639019Smckusick #if defined(tahoe) 18739019Smckusick if ((bp->b_flags & B_READ) == 0) 18839019Smckusick mtpr(P1DC, vaddr); 18939019Smckusick #endif 19039019Smckusick ppte++; 19139019Smckusick pte++; 19239019Smckusick vaddr += NBPG; 19339019Smckusick } 19439019Smckusick } 19539019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 19639019Smckusick if (bp->b_flags & B_READ) 19739019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 19839019Smckusick else 19939019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 20039019Smckusick if (bp->b_error) 20139019Smckusick bp->b_flags |= B_ERROR; 20239019Smckusick /* 20339019Smckusick * Release pte's used by physical I/O. 20439019Smckusick */ 20539019Smckusick if (bp->b_flags & B_PHYS) { 20639019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 20739019Smckusick if (mfsmap_want) { 20839019Smckusick mfsmap_want = 0; 20939019Smckusick wakeup((caddr_t)&mfsmap_want); 21039019Smckusick } 21139019Smckusick } 21239019Smckusick biodone(bp); 21339019Smckusick } 21439019Smckusick 21539019Smckusick /* 21639019Smckusick * Memory filesystem close routine 21739019Smckusick */ 21839019Smckusick /* ARGSUSED */ 21939019Smckusick mfs_close(vp, flag, cred) 22039019Smckusick register struct vnode *vp; 22139019Smckusick int flag; 22239019Smckusick struct ucred *cred; 22339019Smckusick { 22439389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 22539438Smckusick register struct buf *bp; 22639019Smckusick 22739019Smckusick /* 22839438Smckusick * Finish any pending I/O requests. 22939438Smckusick */ 23039438Smckusick while (bp = mfsp->mfs_buflist) { 23139438Smckusick mfsp->mfs_buflist = bp->av_forw; 23239438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 23339438Smckusick wakeup((caddr_t)bp); 23439438Smckusick } 23539438Smckusick /* 23639019Smckusick * On last close of a memory filesystem 23739019Smckusick * we must invalidate any in core blocks, so that 23839019Smckusick * we can, free up its vnode. 23939019Smckusick */ 240*39677Smckusick vflushbuf(vp, 0); 241*39677Smckusick if (vinvalbuf(vp, 1)) 24239019Smckusick return (0); 24339019Smckusick /* 24439438Smckusick * There should be no way to have any more uses of this 24539438Smckusick * vnode, so if we find any other uses, it is a panic. 24639019Smckusick */ 24739438Smckusick if (vp->v_count > 1) 24839019Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_count); 24939438Smckusick if (vp->v_count > 1 || mfsp->mfs_buflist) 25039438Smckusick panic("mfs_close"); 25139019Smckusick /* 25239019Smckusick * Send a request to the filesystem server to exit. 25339019Smckusick */ 25439389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 25539019Smckusick wakeup((caddr_t)vp); 25639019Smckusick return (0); 25739019Smckusick } 25839019Smckusick 25939019Smckusick /* 26039389Smckusick * Memory filesystem inactive routine 26139389Smckusick */ 26239389Smckusick /* ARGSUSED */ 26339389Smckusick mfs_inactive(vp) 26439389Smckusick struct vnode *vp; 26539389Smckusick { 26639389Smckusick 26739389Smckusick if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 26839389Smckusick panic("mfs_inactive: not inactive"); 26939389Smckusick return (0); 27039389Smckusick } 27139389Smckusick 27239389Smckusick /* 273*39677Smckusick * Print out the contents of an mfsnode. 274*39677Smckusick */ 275*39677Smckusick mfs_print(vp) 276*39677Smckusick struct vnode *vp; 277*39677Smckusick { 278*39677Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 279*39677Smckusick 280*39677Smckusick printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 281*39677Smckusick mfsp->mfs_baseoff, mfsp->mfs_size); 282*39677Smckusick } 283*39677Smckusick 284*39677Smckusick /* 28539019Smckusick * Block device bad operation 28639019Smckusick */ 28739019Smckusick mfs_badop() 28839019Smckusick { 28939019Smckusick 29039389Smckusick panic("mfs_badop called\n"); 29139389Smckusick /* NOTREACHED */ 29239019Smckusick } 29339019Smckusick 29439019Smckusick /* 29539019Smckusick * Block device null operation 29639019Smckusick */ 29739019Smckusick mfs_nullop() 29839019Smckusick { 29939019Smckusick 30039019Smckusick return (0); 30139019Smckusick } 30239019Smckusick 30339019Smckusick /* 30439019Smckusick * Memory based filesystem initialization. 30539019Smckusick */ 30639019Smckusick mfs_init() 30739019Smckusick { 30839019Smckusick 30939019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 31039019Smckusick } 311