139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 544536Sbostic * %sccs.include.redist.c% 639019Smckusick * 7*53197Sralph * @(#)mfs_vnops.c 7.30 (Berkeley) 04/19/92 839019Smckusick */ 939019Smckusick 1051477Sbostic #include <sys/param.h> 1151477Sbostic #include <sys/systm.h> 1251477Sbostic #include <sys/time.h> 1351477Sbostic #include <sys/kernel.h> 1451477Sbostic #include <sys/proc.h> 1551477Sbostic #include <sys/buf.h> 1651477Sbostic #include <sys/map.h> 1751477Sbostic #include <sys/vnode.h> 1851981Smckusick #include <sys/malloc.h> 1947571Skarels 2051477Sbostic #include <machine/vmparam.h> 2152784Sralph #if defined(tahoe) 2251477Sbostic #include <machine/mtpr.h> 2352784Sralph #endif 2447571Skarels 2551477Sbostic #include <ufs/mfs/mfsnode.h> 2651477Sbostic #include <ufs/mfs/mfsiom.h> 2751477Sbostic #include <ufs/mfs/mfs_extern.h> 2839019Smckusick 2952907Storek #if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) 3039019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 3139019Smckusick struct map mfsmap[MFS_MAPSIZE]; 3239019Smckusick extern char mfsiobuf[]; 3341536Smckusick #endif 3439019Smckusick 3539019Smckusick /* 3639019Smckusick * mfs vnode operations. 3739019Smckusick */ 3839019Smckusick struct vnodeops mfs_vnodeops = { 3948038Smckusick mfs_lookup, /* lookup */ 4048038Smckusick mfs_create, /* create */ 4148038Smckusick mfs_mknod, /* mknod */ 4239677Smckusick mfs_open, /* open */ 4339677Smckusick mfs_close, /* close */ 4448038Smckusick mfs_access, /* access */ 4548038Smckusick mfs_getattr, /* getattr */ 4648038Smckusick mfs_setattr, /* setattr */ 4748038Smckusick mfs_read, /* read */ 4848038Smckusick mfs_write, /* write */ 4939677Smckusick mfs_ioctl, /* ioctl */ 5048038Smckusick mfs_select, /* select */ 5148038Smckusick mfs_mmap, /* mmap */ 5248038Smckusick mfs_fsync, /* fsync */ 5348038Smckusick mfs_seek, /* seek */ 5448038Smckusick mfs_remove, /* remove */ 5548038Smckusick mfs_link, /* link */ 5648038Smckusick mfs_rename, /* rename */ 5748038Smckusick mfs_mkdir, /* mkdir */ 5848038Smckusick mfs_rmdir, /* rmdir */ 5948038Smckusick mfs_symlink, /* symlink */ 6048038Smckusick mfs_readdir, /* readdir */ 6148038Smckusick mfs_readlink, /* readlink */ 6248038Smckusick mfs_abortop, /* abortop */ 6339677Smckusick mfs_inactive, /* inactive */ 6448038Smckusick mfs_reclaim, /* reclaim */ 6548038Smckusick mfs_lock, /* lock */ 6648038Smckusick mfs_unlock, /* unlock */ 6739680Smckusick mfs_bmap, /* bmap */ 6839677Smckusick mfs_strategy, /* strategy */ 6939677Smckusick mfs_print, /* print */ 7048038Smckusick mfs_islocked, /* islocked */ 7148038Smckusick mfs_advlock, /* advlock */ 7251570Smckusick mfs_blkatoff, /* blkatoff */ 7351570Smckusick mfs_vget, /* vget */ 7451570Smckusick mfs_valloc, /* valloc */ 7551570Smckusick mfs_vfree, /* vfree */ 7651570Smckusick mfs_truncate, /* truncate */ 7751570Smckusick mfs_update, /* update */ 7851570Smckusick mfs_bwrite, /* bwrite */ 7939019Smckusick }; 8039019Smckusick 8139019Smckusick /* 8239019Smckusick * Vnode Operations. 8339019Smckusick * 8439019Smckusick * Open called to allow memory filesystem to initialize and 8539357Smckusick * validate before actual IO. Record our process identifier 8639357Smckusick * so we can tell when we are doing I/O to ourself. 8739019Smckusick */ 8839019Smckusick /* ARGSUSED */ 8951477Sbostic int 9048038Smckusick mfs_open(vp, mode, cred, p) 9139019Smckusick register struct vnode *vp; 9239019Smckusick int mode; 9339019Smckusick struct ucred *cred; 9448038Smckusick struct proc *p; 9539019Smckusick { 9639019Smckusick 9739019Smckusick if (vp->v_type != VBLK) { 9839019Smckusick panic("mfs_ioctl not VBLK"); 9939019Smckusick /* NOTREACHED */ 10039019Smckusick } 10139019Smckusick return (0); 10239019Smckusick } 10339019Smckusick 10439019Smckusick /* 10539019Smckusick * Ioctl operation. 10639019Smckusick */ 10739019Smckusick /* ARGSUSED */ 10851477Sbostic int 10948038Smckusick mfs_ioctl(vp, com, data, fflag, cred, p) 11039019Smckusick struct vnode *vp; 11139019Smckusick int com; 11239019Smckusick caddr_t data; 11339019Smckusick int fflag; 11439019Smckusick struct ucred *cred; 11548038Smckusick struct proc *p; 11639019Smckusick { 11739019Smckusick 11853043Sralph return (ENOTTY); 11939019Smckusick } 12039019Smckusick 12139019Smckusick /* 12239019Smckusick * Pass I/O requests to the memory filesystem process. 12339019Smckusick */ 12451477Sbostic int 12539019Smckusick mfs_strategy(bp) 12639019Smckusick register struct buf *bp; 12739019Smckusick { 12839822Smckusick register struct mfsnode *mfsp; 12939822Smckusick struct vnode *vp; 13048038Smckusick struct proc *p = curproc; /* XXX */ 13139019Smckusick 13239822Smckusick if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 13339822Smckusick panic("mfs_strategy: bad dev"); 13439822Smckusick mfsp = VTOMFS(vp); 13553043Sralph /* check for mini-root access */ 13653043Sralph if (mfsp->mfs_pid == 0) { 13753043Sralph caddr_t base; 13853043Sralph 13953043Sralph base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT); 14053043Sralph if (bp->b_flags & B_READ) 14153043Sralph bcopy(base, bp->b_un.b_addr, bp->b_bcount); 14253043Sralph else 14353043Sralph bcopy(bp->b_un.b_addr, base, bp->b_bcount); 14453043Sralph biodone(bp); 14553043Sralph } else if (mfsp->mfs_pid == p->p_pid) { 14639389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 14739019Smckusick } else { 14839389Smckusick bp->av_forw = mfsp->mfs_buflist; 14939389Smckusick mfsp->mfs_buflist = bp; 15039822Smckusick wakeup((caddr_t)vp); 15139019Smckusick } 15239357Smckusick return (0); 15339019Smckusick } 15439019Smckusick 15543412Shibler #if defined(vax) || defined(tahoe) 15639019Smckusick /* 15739019Smckusick * Memory file system I/O. 15839019Smckusick * 15939019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 16039019Smckusick * doing the copies to or from the memfs process. If doing physio 16139019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 16239019Smckusick * address space. 16339019Smckusick */ 16451477Sbostic void 16539019Smckusick mfs_doio(bp, base) 16639019Smckusick register struct buf *bp; 16739019Smckusick caddr_t base; 16839019Smckusick { 16939019Smckusick register struct pte *pte, *ppte; 17039019Smckusick register caddr_t vaddr; 17139019Smckusick int off, npf, npf2, reg; 17239019Smckusick caddr_t kernaddr, offset; 17339019Smckusick 17439019Smckusick /* 17539019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 17639019Smckusick * the Mfsiomap pte's. 17739019Smckusick */ 17839019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 17939019Smckusick kernaddr = bp->b_un.b_addr; 18039019Smckusick } else { 18139019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 18239019Smckusick panic("swap on memfs?"); 18339019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 18439019Smckusick npf = btoc(bp->b_bcount + off); 18539019Smckusick /* 18639019Smckusick * Get some mapping page table entries 18739019Smckusick */ 18839019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 18939019Smckusick mfsmap_want++; 19039019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 19139019Smckusick } 19239019Smckusick reg--; 19339019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 19439019Smckusick /* 19539019Smckusick * Do vmaccess() but with the Mfsiomap page table. 19639019Smckusick */ 19739019Smckusick ppte = &Mfsiomap[reg]; 19839019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 19939019Smckusick kernaddr = vaddr + off; 20039019Smckusick for (npf2 = npf; npf2; npf2--) { 20139019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 20239019Smckusick (int)(PG_V|PG_KW)); 20339019Smckusick #if defined(tahoe) 20439019Smckusick if ((bp->b_flags & B_READ) == 0) 20539019Smckusick mtpr(P1DC, vaddr); 20639019Smckusick #endif 20739019Smckusick ppte++; 20839019Smckusick pte++; 20939019Smckusick vaddr += NBPG; 21039019Smckusick } 21139019Smckusick } 21239019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 21339019Smckusick if (bp->b_flags & B_READ) 21439019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 21539019Smckusick else 21639019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 21739019Smckusick if (bp->b_error) 21839019Smckusick bp->b_flags |= B_ERROR; 21939019Smckusick /* 22039019Smckusick * Release pte's used by physical I/O. 22139019Smckusick */ 22239019Smckusick if (bp->b_flags & B_PHYS) { 22339019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 22439019Smckusick if (mfsmap_want) { 22539019Smckusick mfsmap_want = 0; 22639019Smckusick wakeup((caddr_t)&mfsmap_want); 22739019Smckusick } 22839019Smckusick } 22939019Smckusick biodone(bp); 23039019Smckusick } 23143412Shibler #endif /* vax || tahoe */ 23239019Smckusick 23352907Storek #if defined(hp300) || defined(i386) || defined(mips) || defined(sparc) 23439019Smckusick /* 23543412Shibler * Memory file system I/O. 23643412Shibler * 23743412Shibler * Trivial on the HP since buffer has already been mapping into KVA space. 23843412Shibler */ 23951477Sbostic void 24043412Shibler mfs_doio(bp, base) 24143412Shibler register struct buf *bp; 24243412Shibler caddr_t base; 24343412Shibler { 24453043Sralph 24543412Shibler base += (bp->b_blkno << DEV_BSHIFT); 24643412Shibler if (bp->b_flags & B_READ) 24743412Shibler bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 24843412Shibler else 24943412Shibler bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 25043412Shibler if (bp->b_error) 25143412Shibler bp->b_flags |= B_ERROR; 25243412Shibler biodone(bp); 25343412Shibler } 25443412Shibler #endif 25543412Shibler 25643412Shibler /* 25739680Smckusick * This is a noop, simply returning what one has been given. 25839680Smckusick */ 25951477Sbostic int 26039680Smckusick mfs_bmap(vp, bn, vpp, bnp) 26139680Smckusick struct vnode *vp; 26239680Smckusick daddr_t bn; 26339680Smckusick struct vnode **vpp; 26439680Smckusick daddr_t *bnp; 26539680Smckusick { 26639680Smckusick 26739680Smckusick if (vpp != NULL) 26839680Smckusick *vpp = vp; 26939680Smckusick if (bnp != NULL) 27039680Smckusick *bnp = bn; 27139680Smckusick return (0); 27239680Smckusick } 27339680Smckusick 27439680Smckusick /* 27539019Smckusick * Memory filesystem close routine 27639019Smckusick */ 27739019Smckusick /* ARGSUSED */ 27851477Sbostic int 27948038Smckusick mfs_close(vp, flag, cred, p) 28039019Smckusick register struct vnode *vp; 28139019Smckusick int flag; 28239019Smckusick struct ucred *cred; 28348038Smckusick struct proc *p; 28439019Smckusick { 28539389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 28639438Smckusick register struct buf *bp; 28739019Smckusick 28839019Smckusick /* 28939438Smckusick * Finish any pending I/O requests. 29039438Smckusick */ 29139438Smckusick while (bp = mfsp->mfs_buflist) { 29239438Smckusick mfsp->mfs_buflist = bp->av_forw; 29339438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 29439438Smckusick wakeup((caddr_t)bp); 29539438Smckusick } 29639438Smckusick /* 29739019Smckusick * On last close of a memory filesystem 29839019Smckusick * we must invalidate any in core blocks, so that 29939019Smckusick * we can, free up its vnode. 30039019Smckusick */ 30139677Smckusick vflushbuf(vp, 0); 30239677Smckusick if (vinvalbuf(vp, 1)) 30339019Smckusick return (0); 30439019Smckusick /* 30539438Smckusick * There should be no way to have any more uses of this 30639438Smckusick * vnode, so if we find any other uses, it is a panic. 30739019Smckusick */ 30839813Smckusick if (vp->v_usecount > 1) 30939813Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 31039813Smckusick if (vp->v_usecount > 1 || mfsp->mfs_buflist) 31139438Smckusick panic("mfs_close"); 31239019Smckusick /* 31339019Smckusick * Send a request to the filesystem server to exit. 31439019Smckusick */ 31539389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 31639019Smckusick wakeup((caddr_t)vp); 31739019Smckusick return (0); 31839019Smckusick } 31939019Smckusick 32039019Smckusick /* 32139389Smckusick * Memory filesystem inactive routine 32239389Smckusick */ 32339389Smckusick /* ARGSUSED */ 32451477Sbostic int 32548038Smckusick mfs_inactive(vp, p) 32639389Smckusick struct vnode *vp; 32748038Smckusick struct proc *p; 32839389Smckusick { 329*53197Sralph register struct mfsnode *mfsp = VTOMFS(vp); 33039389Smckusick 331*53197Sralph if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1)) 332*53197Sralph panic("mfs_inactive: not inactive (mfs_buflist %x)", 333*53197Sralph mfsp->mfs_buflist); 33439389Smckusick return (0); 33539389Smckusick } 33639389Smckusick 33739389Smckusick /* 33851981Smckusick * Reclaim a memory filesystem devvp so that it can be reused. 33951981Smckusick */ 34051981Smckusick int 34151981Smckusick mfs_reclaim(vp) 34251981Smckusick register struct vnode *vp; 34351981Smckusick { 34451981Smckusick 34551981Smckusick FREE(vp->v_data, M_MFSNODE); 34651981Smckusick vp->v_data = NULL; 34751981Smckusick return (0); 34851981Smckusick } 34951981Smckusick 35051981Smckusick /* 35139677Smckusick * Print out the contents of an mfsnode. 35239677Smckusick */ 35351477Sbostic int 35439677Smckusick mfs_print(vp) 35539677Smckusick struct vnode *vp; 35639677Smckusick { 35739677Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 35839677Smckusick 35939677Smckusick printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 36039677Smckusick mfsp->mfs_baseoff, mfsp->mfs_size); 36151477Sbostic return (0); 36239677Smckusick } 36339677Smckusick 36439677Smckusick /* 36539019Smckusick * Block device bad operation 36639019Smckusick */ 36751477Sbostic int 36839019Smckusick mfs_badop() 36939019Smckusick { 37039019Smckusick 37139389Smckusick panic("mfs_badop called\n"); 37239389Smckusick /* NOTREACHED */ 37339019Smckusick } 37439019Smckusick 37539019Smckusick /* 37639019Smckusick * Memory based filesystem initialization. 37739019Smckusick */ 37839019Smckusick mfs_init() 37939019Smckusick { 38039019Smckusick 38152907Storek #if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) 38239019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 38341536Smckusick #endif 38439019Smckusick } 385