139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 544536Sbostic * %sccs.include.redist.c% 639019Smckusick * 7*51035Sralph * @(#)mfs_vnops.c 7.23 (Berkeley) 09/06/91 839019Smckusick */ 939019Smckusick 1039019Smckusick #include "param.h" 1148038Smckusick #include "systm.h" 1239019Smckusick #include "time.h" 1339357Smckusick #include "kernel.h" 1439019Smckusick #include "proc.h" 1539019Smckusick #include "buf.h" 1639019Smckusick #include "map.h" 1739019Smckusick #include "vnode.h" 1847571Skarels 1947571Skarels #include "mfsnode.h" 2047571Skarels #include "mfsiom.h" 2147571Skarels 2239456Smckusick #include "machine/vmparam.h" 2339456Smckusick #include "machine/mtpr.h" 2439019Smckusick 25*51035Sralph #if !defined(hp300) && !defined(i386) && !defined(mips) 2639019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 2739019Smckusick struct map mfsmap[MFS_MAPSIZE]; 2839019Smckusick extern char mfsiobuf[]; 2941536Smckusick #endif 3039019Smckusick 3139019Smckusick /* 3239019Smckusick * mfs vnode operations. 3339019Smckusick */ 3439019Smckusick struct vnodeops mfs_vnodeops = { 3548038Smckusick mfs_lookup, /* lookup */ 3648038Smckusick mfs_create, /* create */ 3748038Smckusick mfs_mknod, /* mknod */ 3839677Smckusick mfs_open, /* open */ 3939677Smckusick mfs_close, /* close */ 4048038Smckusick mfs_access, /* access */ 4148038Smckusick mfs_getattr, /* getattr */ 4248038Smckusick mfs_setattr, /* setattr */ 4348038Smckusick mfs_read, /* read */ 4448038Smckusick mfs_write, /* write */ 4539677Smckusick mfs_ioctl, /* ioctl */ 4648038Smckusick mfs_select, /* select */ 4748038Smckusick mfs_mmap, /* mmap */ 4848038Smckusick mfs_fsync, /* fsync */ 4948038Smckusick mfs_seek, /* seek */ 5048038Smckusick mfs_remove, /* remove */ 5148038Smckusick mfs_link, /* link */ 5248038Smckusick mfs_rename, /* rename */ 5348038Smckusick mfs_mkdir, /* mkdir */ 5448038Smckusick mfs_rmdir, /* rmdir */ 5548038Smckusick mfs_symlink, /* symlink */ 5648038Smckusick mfs_readdir, /* readdir */ 5748038Smckusick mfs_readlink, /* readlink */ 5848038Smckusick mfs_abortop, /* abortop */ 5939677Smckusick mfs_inactive, /* inactive */ 6048038Smckusick mfs_reclaim, /* reclaim */ 6148038Smckusick mfs_lock, /* lock */ 6248038Smckusick mfs_unlock, /* unlock */ 6339680Smckusick mfs_bmap, /* bmap */ 6439677Smckusick mfs_strategy, /* strategy */ 6539677Smckusick mfs_print, /* print */ 6648038Smckusick mfs_islocked, /* islocked */ 6748038Smckusick mfs_advlock, /* advlock */ 6839019Smckusick }; 6939019Smckusick 7039019Smckusick /* 7139019Smckusick * Vnode Operations. 7239019Smckusick * 7339019Smckusick * Open called to allow memory filesystem to initialize and 7439357Smckusick * validate before actual IO. Record our process identifier 7539357Smckusick * so we can tell when we are doing I/O to ourself. 7639019Smckusick */ 7739019Smckusick /* ARGSUSED */ 7848038Smckusick mfs_open(vp, mode, cred, p) 7939019Smckusick register struct vnode *vp; 8039019Smckusick int mode; 8139019Smckusick struct ucred *cred; 8248038Smckusick struct proc *p; 8339019Smckusick { 8439019Smckusick 8539019Smckusick if (vp->v_type != VBLK) { 8639019Smckusick panic("mfs_ioctl not VBLK"); 8739019Smckusick /* NOTREACHED */ 8839019Smckusick } 8939019Smckusick return (0); 9039019Smckusick } 9139019Smckusick 9239019Smckusick /* 9339019Smckusick * Ioctl operation. 9439019Smckusick */ 9539019Smckusick /* ARGSUSED */ 9648038Smckusick mfs_ioctl(vp, com, data, fflag, cred, p) 9739019Smckusick struct vnode *vp; 9839019Smckusick int com; 9939019Smckusick caddr_t data; 10039019Smckusick int fflag; 10139019Smckusick struct ucred *cred; 10248038Smckusick struct proc *p; 10339019Smckusick { 10439019Smckusick 10539019Smckusick return (-1); 10639019Smckusick } 10739019Smckusick 10839019Smckusick /* 10939019Smckusick * Pass I/O requests to the memory filesystem process. 11039019Smckusick */ 11139019Smckusick mfs_strategy(bp) 11239019Smckusick register struct buf *bp; 11339019Smckusick { 11439822Smckusick register struct mfsnode *mfsp; 11539822Smckusick struct vnode *vp; 11648038Smckusick struct proc *p = curproc; /* XXX */ 11739019Smckusick 11839822Smckusick if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 11939822Smckusick panic("mfs_strategy: bad dev"); 12039822Smckusick mfsp = VTOMFS(vp); 12148038Smckusick if (mfsp->mfs_pid == p->p_pid) { 12239389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 12339019Smckusick } else { 12439389Smckusick bp->av_forw = mfsp->mfs_buflist; 12539389Smckusick mfsp->mfs_buflist = bp; 12639822Smckusick wakeup((caddr_t)vp); 12739019Smckusick } 12839357Smckusick return (0); 12939019Smckusick } 13039019Smckusick 13143412Shibler #if defined(vax) || defined(tahoe) 13239019Smckusick /* 13339019Smckusick * Memory file system I/O. 13439019Smckusick * 13539019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 13639019Smckusick * doing the copies to or from the memfs process. If doing physio 13739019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 13839019Smckusick * address space. 13939019Smckusick */ 14039019Smckusick mfs_doio(bp, base) 14139019Smckusick register struct buf *bp; 14239019Smckusick caddr_t base; 14339019Smckusick { 14439019Smckusick register struct pte *pte, *ppte; 14539019Smckusick register caddr_t vaddr; 14639019Smckusick int off, npf, npf2, reg; 14739019Smckusick caddr_t kernaddr, offset; 14839019Smckusick 14939019Smckusick /* 15039019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 15139019Smckusick * the Mfsiomap pte's. 15239019Smckusick */ 15339019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 15439019Smckusick kernaddr = bp->b_un.b_addr; 15539019Smckusick } else { 15639019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 15739019Smckusick panic("swap on memfs?"); 15839019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 15939019Smckusick npf = btoc(bp->b_bcount + off); 16039019Smckusick /* 16139019Smckusick * Get some mapping page table entries 16239019Smckusick */ 16339019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 16439019Smckusick mfsmap_want++; 16539019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 16639019Smckusick } 16739019Smckusick reg--; 16839019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 16939019Smckusick /* 17039019Smckusick * Do vmaccess() but with the Mfsiomap page table. 17139019Smckusick */ 17239019Smckusick ppte = &Mfsiomap[reg]; 17339019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 17439019Smckusick kernaddr = vaddr + off; 17539019Smckusick for (npf2 = npf; npf2; npf2--) { 17639019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 17739019Smckusick (int)(PG_V|PG_KW)); 17839019Smckusick #if defined(tahoe) 17939019Smckusick if ((bp->b_flags & B_READ) == 0) 18039019Smckusick mtpr(P1DC, vaddr); 18139019Smckusick #endif 18239019Smckusick ppte++; 18339019Smckusick pte++; 18439019Smckusick vaddr += NBPG; 18539019Smckusick } 18639019Smckusick } 18739019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 18839019Smckusick if (bp->b_flags & B_READ) 18939019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 19039019Smckusick else 19139019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 19239019Smckusick if (bp->b_error) 19339019Smckusick bp->b_flags |= B_ERROR; 19439019Smckusick /* 19539019Smckusick * Release pte's used by physical I/O. 19639019Smckusick */ 19739019Smckusick if (bp->b_flags & B_PHYS) { 19839019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 19939019Smckusick if (mfsmap_want) { 20039019Smckusick mfsmap_want = 0; 20139019Smckusick wakeup((caddr_t)&mfsmap_want); 20239019Smckusick } 20339019Smckusick } 20439019Smckusick biodone(bp); 20539019Smckusick } 20643412Shibler #endif /* vax || tahoe */ 20739019Smckusick 208*51035Sralph #if defined(hp300) || defined(i386) || defined(mips) 20939019Smckusick /* 21043412Shibler * Memory file system I/O. 21143412Shibler * 21243412Shibler * Trivial on the HP since buffer has already been mapping into KVA space. 21343412Shibler */ 21443412Shibler mfs_doio(bp, base) 21543412Shibler register struct buf *bp; 21643412Shibler caddr_t base; 21743412Shibler { 21843412Shibler base += (bp->b_blkno << DEV_BSHIFT); 21943412Shibler if (bp->b_flags & B_READ) 22043412Shibler bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 22143412Shibler else 22243412Shibler bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 22343412Shibler if (bp->b_error) 22443412Shibler bp->b_flags |= B_ERROR; 22543412Shibler biodone(bp); 22643412Shibler } 22743412Shibler #endif 22843412Shibler 22943412Shibler /* 23039680Smckusick * This is a noop, simply returning what one has been given. 23139680Smckusick */ 23239680Smckusick mfs_bmap(vp, bn, vpp, bnp) 23339680Smckusick struct vnode *vp; 23439680Smckusick daddr_t bn; 23539680Smckusick struct vnode **vpp; 23639680Smckusick daddr_t *bnp; 23739680Smckusick { 23839680Smckusick 23939680Smckusick if (vpp != NULL) 24039680Smckusick *vpp = vp; 24139680Smckusick if (bnp != NULL) 24239680Smckusick *bnp = bn; 24339680Smckusick return (0); 24439680Smckusick } 24539680Smckusick 24639680Smckusick /* 24739019Smckusick * Memory filesystem close routine 24839019Smckusick */ 24939019Smckusick /* ARGSUSED */ 25048038Smckusick mfs_close(vp, flag, cred, p) 25139019Smckusick register struct vnode *vp; 25239019Smckusick int flag; 25339019Smckusick struct ucred *cred; 25448038Smckusick struct proc *p; 25539019Smckusick { 25639389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 25739438Smckusick register struct buf *bp; 25839019Smckusick 25939019Smckusick /* 26039438Smckusick * Finish any pending I/O requests. 26139438Smckusick */ 26239438Smckusick while (bp = mfsp->mfs_buflist) { 26339438Smckusick mfsp->mfs_buflist = bp->av_forw; 26439438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 26539438Smckusick wakeup((caddr_t)bp); 26639438Smckusick } 26739438Smckusick /* 26839019Smckusick * On last close of a memory filesystem 26939019Smckusick * we must invalidate any in core blocks, so that 27039019Smckusick * we can, free up its vnode. 27139019Smckusick */ 27239677Smckusick vflushbuf(vp, 0); 27339677Smckusick if (vinvalbuf(vp, 1)) 27439019Smckusick return (0); 27539019Smckusick /* 27639438Smckusick * There should be no way to have any more uses of this 27739438Smckusick * vnode, so if we find any other uses, it is a panic. 27839019Smckusick */ 27939813Smckusick if (vp->v_usecount > 1) 28039813Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 28139813Smckusick if (vp->v_usecount > 1 || mfsp->mfs_buflist) 28239438Smckusick panic("mfs_close"); 28339019Smckusick /* 28439019Smckusick * Send a request to the filesystem server to exit. 28539019Smckusick */ 28639389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 28739019Smckusick wakeup((caddr_t)vp); 28839019Smckusick return (0); 28939019Smckusick } 29039019Smckusick 29139019Smckusick /* 29239389Smckusick * Memory filesystem inactive routine 29339389Smckusick */ 29439389Smckusick /* ARGSUSED */ 29548038Smckusick mfs_inactive(vp, p) 29639389Smckusick struct vnode *vp; 29748038Smckusick struct proc *p; 29839389Smckusick { 29939389Smckusick 30039389Smckusick if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 30139389Smckusick panic("mfs_inactive: not inactive"); 30239389Smckusick return (0); 30339389Smckusick } 30439389Smckusick 30539389Smckusick /* 30639677Smckusick * Print out the contents of an mfsnode. 30739677Smckusick */ 30839677Smckusick mfs_print(vp) 30939677Smckusick struct vnode *vp; 31039677Smckusick { 31139677Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 31239677Smckusick 31339677Smckusick printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 31439677Smckusick mfsp->mfs_baseoff, mfsp->mfs_size); 31539677Smckusick } 31639677Smckusick 31739677Smckusick /* 31839019Smckusick * Block device bad operation 31939019Smckusick */ 32039019Smckusick mfs_badop() 32139019Smckusick { 32239019Smckusick 32339389Smckusick panic("mfs_badop called\n"); 32439389Smckusick /* NOTREACHED */ 32539019Smckusick } 32639019Smckusick 32739019Smckusick /* 32839019Smckusick * Memory based filesystem initialization. 32939019Smckusick */ 33039019Smckusick mfs_init() 33139019Smckusick { 33239019Smckusick 333*51035Sralph #if !defined(hp300) && !defined(i386) && !defined(mips) 33439019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 33541536Smckusick #endif 33639019Smckusick } 337