139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 5*44536Sbostic * %sccs.include.redist.c% 639019Smckusick * 7*44536Sbostic * @(#)mfs_vnops.c 7.17 (Berkeley) 06/28/90 839019Smckusick */ 939019Smckusick 1039019Smckusick #include "param.h" 1139019Smckusick #include "time.h" 1239357Smckusick #include "kernel.h" 1339019Smckusick #include "proc.h" 1439357Smckusick #include "user.h" 1539019Smckusick #include "buf.h" 1639019Smckusick #include "vmmac.h" 1739019Smckusick #include "errno.h" 1839019Smckusick #include "map.h" 1939019Smckusick #include "vnode.h" 2039389Smckusick #include "../ufs/mfsnode.h" 2139019Smckusick #include "../ufs/mfsiom.h" 2239456Smckusick #include "machine/vmparam.h" 2339456Smckusick #include "machine/pte.h" 2439456Smckusick #include "machine/mtpr.h" 2539019Smckusick 2641536Smckusick #if !defined(hp300) 2739019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 2839019Smckusick struct map mfsmap[MFS_MAPSIZE]; 2939019Smckusick extern char mfsiobuf[]; 3041536Smckusick #endif 3139019Smckusick 3239019Smckusick /* 3339019Smckusick * mfs vnode operations. 3439019Smckusick */ 3539019Smckusick int mfs_open(), 3639019Smckusick mfs_strategy(), 3739680Smckusick mfs_bmap(), 3839019Smckusick mfs_ioctl(), 3939019Smckusick mfs_close(), 4039389Smckusick mfs_inactive(), 4139677Smckusick mfs_print(), 4239019Smckusick mfs_badop(), 4339019Smckusick mfs_nullop(); 4439019Smckusick 4539019Smckusick struct vnodeops mfs_vnodeops = { 4639677Smckusick mfs_badop, /* lookup */ 4739677Smckusick mfs_badop, /* create */ 4839677Smckusick mfs_badop, /* mknod */ 4939677Smckusick mfs_open, /* open */ 5039677Smckusick mfs_close, /* close */ 5139677Smckusick mfs_badop, /* access */ 5239677Smckusick mfs_badop, /* getattr */ 5339677Smckusick mfs_badop, /* setattr */ 5439677Smckusick mfs_badop, /* read */ 5539677Smckusick mfs_badop, /* write */ 5639677Smckusick mfs_ioctl, /* ioctl */ 5739677Smckusick mfs_badop, /* select */ 5839677Smckusick mfs_badop, /* mmap */ 5939677Smckusick mfs_badop, /* fsync */ 6039677Smckusick mfs_badop, /* seek */ 6139677Smckusick mfs_badop, /* remove */ 6239677Smckusick mfs_badop, /* link */ 6339677Smckusick mfs_badop, /* rename */ 6439677Smckusick mfs_badop, /* mkdir */ 6539677Smckusick mfs_badop, /* rmdir */ 6639677Smckusick mfs_badop, /* symlink */ 6739677Smckusick mfs_badop, /* readdir */ 6839677Smckusick mfs_badop, /* readlink */ 6939677Smckusick mfs_badop, /* abortop */ 7039677Smckusick mfs_inactive, /* inactive */ 7139677Smckusick mfs_nullop, /* reclaim */ 7239852Smckusick mfs_nullop, /* lock */ 7339852Smckusick mfs_nullop, /* unlock */ 7439680Smckusick mfs_bmap, /* bmap */ 7539677Smckusick mfs_strategy, /* strategy */ 7639677Smckusick mfs_print, /* print */ 7739910Smckusick mfs_nullop, /* islocked */ 7839019Smckusick }; 7939019Smckusick 8039019Smckusick /* 8139019Smckusick * Vnode Operations. 8239019Smckusick * 8339019Smckusick * Open called to allow memory filesystem to initialize and 8439357Smckusick * validate before actual IO. Record our process identifier 8539357Smckusick * so we can tell when we are doing I/O to ourself. 8639019Smckusick */ 8739019Smckusick /* ARGSUSED */ 8839019Smckusick mfs_open(vp, mode, cred) 8939019Smckusick register struct vnode *vp; 9039019Smckusick int mode; 9139019Smckusick struct ucred *cred; 9239019Smckusick { 9339019Smckusick 9439019Smckusick if (vp->v_type != VBLK) { 9539019Smckusick panic("mfs_ioctl not VBLK"); 9639019Smckusick /* NOTREACHED */ 9739019Smckusick } 9839019Smckusick return (0); 9939019Smckusick } 10039019Smckusick 10139019Smckusick /* 10239019Smckusick * Ioctl operation. 10339019Smckusick */ 10439019Smckusick /* ARGSUSED */ 10539019Smckusick mfs_ioctl(vp, com, data, fflag, cred) 10639019Smckusick struct vnode *vp; 10739019Smckusick int com; 10839019Smckusick caddr_t data; 10939019Smckusick int fflag; 11039019Smckusick struct ucred *cred; 11139019Smckusick { 11239019Smckusick 11339019Smckusick return (-1); 11439019Smckusick } 11539019Smckusick 11639019Smckusick /* 11739019Smckusick * Pass I/O requests to the memory filesystem process. 11839019Smckusick */ 11939019Smckusick mfs_strategy(bp) 12039019Smckusick register struct buf *bp; 12139019Smckusick { 12239822Smckusick register struct mfsnode *mfsp; 12339822Smckusick struct vnode *vp; 12439019Smckusick 12539822Smckusick if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 12639822Smckusick panic("mfs_strategy: bad dev"); 12739822Smckusick mfsp = VTOMFS(vp); 12839389Smckusick if (mfsp->mfs_pid == u.u_procp->p_pid) { 12939389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 13039019Smckusick } else { 13139389Smckusick bp->av_forw = mfsp->mfs_buflist; 13239389Smckusick mfsp->mfs_buflist = bp; 13339822Smckusick wakeup((caddr_t)vp); 13439019Smckusick } 13539357Smckusick return (0); 13639019Smckusick } 13739019Smckusick 13843412Shibler #if defined(vax) || defined(tahoe) 13939019Smckusick /* 14039019Smckusick * Memory file system I/O. 14139019Smckusick * 14239019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 14339019Smckusick * doing the copies to or from the memfs process. If doing physio 14439019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 14539019Smckusick * address space. 14639019Smckusick */ 14739019Smckusick mfs_doio(bp, base) 14839019Smckusick register struct buf *bp; 14939019Smckusick caddr_t base; 15039019Smckusick { 15139019Smckusick register struct pte *pte, *ppte; 15239019Smckusick register caddr_t vaddr; 15339019Smckusick int off, npf, npf2, reg; 15439019Smckusick caddr_t kernaddr, offset; 15539019Smckusick 15639019Smckusick /* 15739019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 15839019Smckusick * the Mfsiomap pte's. 15939019Smckusick */ 16039019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 16139019Smckusick kernaddr = bp->b_un.b_addr; 16239019Smckusick } else { 16339019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 16439019Smckusick panic("swap on memfs?"); 16539019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 16639019Smckusick npf = btoc(bp->b_bcount + off); 16739019Smckusick /* 16839019Smckusick * Get some mapping page table entries 16939019Smckusick */ 17039019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 17139019Smckusick mfsmap_want++; 17239019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 17339019Smckusick } 17439019Smckusick reg--; 17539019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 17639019Smckusick /* 17739019Smckusick * Do vmaccess() but with the Mfsiomap page table. 17839019Smckusick */ 17939019Smckusick ppte = &Mfsiomap[reg]; 18039019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 18139019Smckusick kernaddr = vaddr + off; 18239019Smckusick for (npf2 = npf; npf2; npf2--) { 18339019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 18439019Smckusick (int)(PG_V|PG_KW)); 18539019Smckusick #if defined(tahoe) 18639019Smckusick if ((bp->b_flags & B_READ) == 0) 18739019Smckusick mtpr(P1DC, vaddr); 18839019Smckusick #endif 18939019Smckusick ppte++; 19039019Smckusick pte++; 19139019Smckusick vaddr += NBPG; 19239019Smckusick } 19339019Smckusick } 19439019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 19539019Smckusick if (bp->b_flags & B_READ) 19639019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 19739019Smckusick else 19839019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 19939019Smckusick if (bp->b_error) 20039019Smckusick bp->b_flags |= B_ERROR; 20139019Smckusick /* 20239019Smckusick * Release pte's used by physical I/O. 20339019Smckusick */ 20439019Smckusick if (bp->b_flags & B_PHYS) { 20539019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 20639019Smckusick if (mfsmap_want) { 20739019Smckusick mfsmap_want = 0; 20839019Smckusick wakeup((caddr_t)&mfsmap_want); 20939019Smckusick } 21039019Smckusick } 21139019Smckusick biodone(bp); 21239019Smckusick } 21343412Shibler #endif /* vax || tahoe */ 21439019Smckusick 21543412Shibler #if defined(hp300) 21639019Smckusick /* 21743412Shibler * Memory file system I/O. 21843412Shibler * 21943412Shibler * Trivial on the HP since buffer has already been mapping into KVA space. 22043412Shibler */ 22143412Shibler mfs_doio(bp, base) 22243412Shibler register struct buf *bp; 22343412Shibler caddr_t base; 22443412Shibler { 22543412Shibler base += (bp->b_blkno << DEV_BSHIFT); 22643412Shibler if (bp->b_flags & B_READ) 22743412Shibler bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 22843412Shibler else 22943412Shibler bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 23043412Shibler if (bp->b_error) 23143412Shibler bp->b_flags |= B_ERROR; 23243412Shibler biodone(bp); 23343412Shibler } 23443412Shibler #endif 23543412Shibler 23643412Shibler /* 23739680Smckusick * This is a noop, simply returning what one has been given. 23839680Smckusick */ 23939680Smckusick mfs_bmap(vp, bn, vpp, bnp) 24039680Smckusick struct vnode *vp; 24139680Smckusick daddr_t bn; 24239680Smckusick struct vnode **vpp; 24339680Smckusick daddr_t *bnp; 24439680Smckusick { 24539680Smckusick 24639680Smckusick if (vpp != NULL) 24739680Smckusick *vpp = vp; 24839680Smckusick if (bnp != NULL) 24939680Smckusick *bnp = bn; 25039680Smckusick return (0); 25139680Smckusick } 25239680Smckusick 25339680Smckusick /* 25439019Smckusick * Memory filesystem close routine 25539019Smckusick */ 25639019Smckusick /* ARGSUSED */ 25739019Smckusick mfs_close(vp, flag, cred) 25839019Smckusick register struct vnode *vp; 25939019Smckusick int flag; 26039019Smckusick struct ucred *cred; 26139019Smckusick { 26239389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 26339438Smckusick register struct buf *bp; 26439019Smckusick 26539019Smckusick /* 26639438Smckusick * Finish any pending I/O requests. 26739438Smckusick */ 26839438Smckusick while (bp = mfsp->mfs_buflist) { 26939438Smckusick mfsp->mfs_buflist = bp->av_forw; 27039438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 27139438Smckusick wakeup((caddr_t)bp); 27239438Smckusick } 27339438Smckusick /* 27439019Smckusick * On last close of a memory filesystem 27539019Smckusick * we must invalidate any in core blocks, so that 27639019Smckusick * we can, free up its vnode. 27739019Smckusick */ 27839677Smckusick vflushbuf(vp, 0); 27939677Smckusick if (vinvalbuf(vp, 1)) 28039019Smckusick return (0); 28139019Smckusick /* 28239438Smckusick * There should be no way to have any more uses of this 28339438Smckusick * vnode, so if we find any other uses, it is a panic. 28439019Smckusick */ 28539813Smckusick if (vp->v_usecount > 1) 28639813Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 28739813Smckusick if (vp->v_usecount > 1 || mfsp->mfs_buflist) 28839438Smckusick panic("mfs_close"); 28939019Smckusick /* 29039019Smckusick * Send a request to the filesystem server to exit. 29139019Smckusick */ 29239389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 29339019Smckusick wakeup((caddr_t)vp); 29439019Smckusick return (0); 29539019Smckusick } 29639019Smckusick 29739019Smckusick /* 29839389Smckusick * Memory filesystem inactive routine 29939389Smckusick */ 30039389Smckusick /* ARGSUSED */ 30139389Smckusick mfs_inactive(vp) 30239389Smckusick struct vnode *vp; 30339389Smckusick { 30439389Smckusick 30539389Smckusick if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 30639389Smckusick panic("mfs_inactive: not inactive"); 30739389Smckusick return (0); 30839389Smckusick } 30939389Smckusick 31039389Smckusick /* 31139677Smckusick * Print out the contents of an mfsnode. 31239677Smckusick */ 31339677Smckusick mfs_print(vp) 31439677Smckusick struct vnode *vp; 31539677Smckusick { 31639677Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 31739677Smckusick 31839677Smckusick printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 31939677Smckusick mfsp->mfs_baseoff, mfsp->mfs_size); 32039677Smckusick } 32139677Smckusick 32239677Smckusick /* 32339019Smckusick * Block device bad operation 32439019Smckusick */ 32539019Smckusick mfs_badop() 32639019Smckusick { 32739019Smckusick 32839389Smckusick panic("mfs_badop called\n"); 32939389Smckusick /* NOTREACHED */ 33039019Smckusick } 33139019Smckusick 33239019Smckusick /* 33339019Smckusick * Block device null operation 33439019Smckusick */ 33539019Smckusick mfs_nullop() 33639019Smckusick { 33739019Smckusick 33839019Smckusick return (0); 33939019Smckusick } 34039019Smckusick 34139019Smckusick /* 34239019Smckusick * Memory based filesystem initialization. 34339019Smckusick */ 34439019Smckusick mfs_init() 34539019Smckusick { 34639019Smckusick 34741536Smckusick #if !defined(hp300) 34839019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 34941536Smckusick #endif 35039019Smckusick } 351