139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 544536Sbostic * %sccs.include.redist.c% 639019Smckusick * 7*51477Sbostic * @(#)mfs_vnops.c 7.24 (Berkeley) 11/01/91 839019Smckusick */ 939019Smckusick 10*51477Sbostic #include <sys/param.h> 11*51477Sbostic #include <sys/systm.h> 12*51477Sbostic #include <sys/time.h> 13*51477Sbostic #include <sys/kernel.h> 14*51477Sbostic #include <sys/proc.h> 15*51477Sbostic #include <sys/buf.h> 16*51477Sbostic #include <sys/map.h> 17*51477Sbostic #include <sys/vnode.h> 1847571Skarels 19*51477Sbostic #include <machine/vmparam.h> 20*51477Sbostic #include <machine/mtpr.h> 2147571Skarels 22*51477Sbostic #include <ufs/mfs/mfsnode.h> 23*51477Sbostic #include <ufs/mfs/mfsiom.h> 24*51477Sbostic #include <ufs/mfs/mfs_extern.h> 2539019Smckusick 2651035Sralph #if !defined(hp300) && !defined(i386) && !defined(mips) 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 struct vnodeops mfs_vnodeops = { 3648038Smckusick mfs_lookup, /* lookup */ 3748038Smckusick mfs_create, /* create */ 3848038Smckusick mfs_mknod, /* mknod */ 3939677Smckusick mfs_open, /* open */ 4039677Smckusick mfs_close, /* close */ 4148038Smckusick mfs_access, /* access */ 4248038Smckusick mfs_getattr, /* getattr */ 4348038Smckusick mfs_setattr, /* setattr */ 4448038Smckusick mfs_read, /* read */ 4548038Smckusick mfs_write, /* write */ 4639677Smckusick mfs_ioctl, /* ioctl */ 4748038Smckusick mfs_select, /* select */ 4848038Smckusick mfs_mmap, /* mmap */ 4948038Smckusick mfs_fsync, /* fsync */ 5048038Smckusick mfs_seek, /* seek */ 5148038Smckusick mfs_remove, /* remove */ 5248038Smckusick mfs_link, /* link */ 5348038Smckusick mfs_rename, /* rename */ 5448038Smckusick mfs_mkdir, /* mkdir */ 5548038Smckusick mfs_rmdir, /* rmdir */ 5648038Smckusick mfs_symlink, /* symlink */ 5748038Smckusick mfs_readdir, /* readdir */ 5848038Smckusick mfs_readlink, /* readlink */ 5948038Smckusick mfs_abortop, /* abortop */ 6039677Smckusick mfs_inactive, /* inactive */ 6148038Smckusick mfs_reclaim, /* reclaim */ 6248038Smckusick mfs_lock, /* lock */ 6348038Smckusick mfs_unlock, /* unlock */ 6439680Smckusick mfs_bmap, /* bmap */ 6539677Smckusick mfs_strategy, /* strategy */ 6639677Smckusick mfs_print, /* print */ 6748038Smckusick mfs_islocked, /* islocked */ 6848038Smckusick mfs_advlock, /* advlock */ 6939019Smckusick }; 7039019Smckusick 7139019Smckusick /* 7239019Smckusick * Vnode Operations. 7339019Smckusick * 7439019Smckusick * Open called to allow memory filesystem to initialize and 7539357Smckusick * validate before actual IO. Record our process identifier 7639357Smckusick * so we can tell when we are doing I/O to ourself. 7739019Smckusick */ 7839019Smckusick /* ARGSUSED */ 79*51477Sbostic int 8048038Smckusick mfs_open(vp, mode, cred, p) 8139019Smckusick register struct vnode *vp; 8239019Smckusick int mode; 8339019Smckusick struct ucred *cred; 8448038Smckusick struct proc *p; 8539019Smckusick { 8639019Smckusick 8739019Smckusick if (vp->v_type != VBLK) { 8839019Smckusick panic("mfs_ioctl not VBLK"); 8939019Smckusick /* NOTREACHED */ 9039019Smckusick } 9139019Smckusick return (0); 9239019Smckusick } 9339019Smckusick 9439019Smckusick /* 9539019Smckusick * Ioctl operation. 9639019Smckusick */ 9739019Smckusick /* ARGSUSED */ 98*51477Sbostic int 9948038Smckusick mfs_ioctl(vp, com, data, fflag, cred, p) 10039019Smckusick struct vnode *vp; 10139019Smckusick int com; 10239019Smckusick caddr_t data; 10339019Smckusick int fflag; 10439019Smckusick struct ucred *cred; 10548038Smckusick struct proc *p; 10639019Smckusick { 10739019Smckusick 10839019Smckusick return (-1); 10939019Smckusick } 11039019Smckusick 11139019Smckusick /* 11239019Smckusick * Pass I/O requests to the memory filesystem process. 11339019Smckusick */ 114*51477Sbostic int 11539019Smckusick mfs_strategy(bp) 11639019Smckusick register struct buf *bp; 11739019Smckusick { 11839822Smckusick register struct mfsnode *mfsp; 11939822Smckusick struct vnode *vp; 12048038Smckusick struct proc *p = curproc; /* XXX */ 12139019Smckusick 12239822Smckusick if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 12339822Smckusick panic("mfs_strategy: bad dev"); 12439822Smckusick mfsp = VTOMFS(vp); 12548038Smckusick if (mfsp->mfs_pid == p->p_pid) { 12639389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 12739019Smckusick } else { 12839389Smckusick bp->av_forw = mfsp->mfs_buflist; 12939389Smckusick mfsp->mfs_buflist = bp; 13039822Smckusick wakeup((caddr_t)vp); 13139019Smckusick } 13239357Smckusick return (0); 13339019Smckusick } 13439019Smckusick 13543412Shibler #if defined(vax) || defined(tahoe) 13639019Smckusick /* 13739019Smckusick * Memory file system I/O. 13839019Smckusick * 13939019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 14039019Smckusick * doing the copies to or from the memfs process. If doing physio 14139019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 14239019Smckusick * address space. 14339019Smckusick */ 144*51477Sbostic void 14539019Smckusick mfs_doio(bp, base) 14639019Smckusick register struct buf *bp; 14739019Smckusick caddr_t base; 14839019Smckusick { 14939019Smckusick register struct pte *pte, *ppte; 15039019Smckusick register caddr_t vaddr; 15139019Smckusick int off, npf, npf2, reg; 15239019Smckusick caddr_t kernaddr, offset; 15339019Smckusick 15439019Smckusick /* 15539019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 15639019Smckusick * the Mfsiomap pte's. 15739019Smckusick */ 15839019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 15939019Smckusick kernaddr = bp->b_un.b_addr; 16039019Smckusick } else { 16139019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 16239019Smckusick panic("swap on memfs?"); 16339019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 16439019Smckusick npf = btoc(bp->b_bcount + off); 16539019Smckusick /* 16639019Smckusick * Get some mapping page table entries 16739019Smckusick */ 16839019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 16939019Smckusick mfsmap_want++; 17039019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 17139019Smckusick } 17239019Smckusick reg--; 17339019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 17439019Smckusick /* 17539019Smckusick * Do vmaccess() but with the Mfsiomap page table. 17639019Smckusick */ 17739019Smckusick ppte = &Mfsiomap[reg]; 17839019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 17939019Smckusick kernaddr = vaddr + off; 18039019Smckusick for (npf2 = npf; npf2; npf2--) { 18139019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 18239019Smckusick (int)(PG_V|PG_KW)); 18339019Smckusick #if defined(tahoe) 18439019Smckusick if ((bp->b_flags & B_READ) == 0) 18539019Smckusick mtpr(P1DC, vaddr); 18639019Smckusick #endif 18739019Smckusick ppte++; 18839019Smckusick pte++; 18939019Smckusick vaddr += NBPG; 19039019Smckusick } 19139019Smckusick } 19239019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 19339019Smckusick if (bp->b_flags & B_READ) 19439019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 19539019Smckusick else 19639019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 19739019Smckusick if (bp->b_error) 19839019Smckusick bp->b_flags |= B_ERROR; 19939019Smckusick /* 20039019Smckusick * Release pte's used by physical I/O. 20139019Smckusick */ 20239019Smckusick if (bp->b_flags & B_PHYS) { 20339019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 20439019Smckusick if (mfsmap_want) { 20539019Smckusick mfsmap_want = 0; 20639019Smckusick wakeup((caddr_t)&mfsmap_want); 20739019Smckusick } 20839019Smckusick } 20939019Smckusick biodone(bp); 21039019Smckusick } 21143412Shibler #endif /* vax || tahoe */ 21239019Smckusick 21351035Sralph #if defined(hp300) || defined(i386) || defined(mips) 21439019Smckusick /* 21543412Shibler * Memory file system I/O. 21643412Shibler * 21743412Shibler * Trivial on the HP since buffer has already been mapping into KVA space. 21843412Shibler */ 219*51477Sbostic void 22043412Shibler mfs_doio(bp, base) 22143412Shibler register struct buf *bp; 22243412Shibler caddr_t base; 22343412Shibler { 22443412Shibler base += (bp->b_blkno << DEV_BSHIFT); 22543412Shibler if (bp->b_flags & B_READ) 22643412Shibler bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 22743412Shibler else 22843412Shibler bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 22943412Shibler if (bp->b_error) 23043412Shibler bp->b_flags |= B_ERROR; 23143412Shibler biodone(bp); 23243412Shibler } 23343412Shibler #endif 23443412Shibler 23543412Shibler /* 23639680Smckusick * This is a noop, simply returning what one has been given. 23739680Smckusick */ 238*51477Sbostic int 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 */ 257*51477Sbostic int 25848038Smckusick mfs_close(vp, flag, cred, p) 25939019Smckusick register struct vnode *vp; 26039019Smckusick int flag; 26139019Smckusick struct ucred *cred; 26248038Smckusick struct proc *p; 26339019Smckusick { 26439389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 26539438Smckusick register struct buf *bp; 26639019Smckusick 26739019Smckusick /* 26839438Smckusick * Finish any pending I/O requests. 26939438Smckusick */ 27039438Smckusick while (bp = mfsp->mfs_buflist) { 27139438Smckusick mfsp->mfs_buflist = bp->av_forw; 27239438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 27339438Smckusick wakeup((caddr_t)bp); 27439438Smckusick } 27539438Smckusick /* 27639019Smckusick * On last close of a memory filesystem 27739019Smckusick * we must invalidate any in core blocks, so that 27839019Smckusick * we can, free up its vnode. 27939019Smckusick */ 28039677Smckusick vflushbuf(vp, 0); 28139677Smckusick if (vinvalbuf(vp, 1)) 28239019Smckusick return (0); 28339019Smckusick /* 28439438Smckusick * There should be no way to have any more uses of this 28539438Smckusick * vnode, so if we find any other uses, it is a panic. 28639019Smckusick */ 28739813Smckusick if (vp->v_usecount > 1) 28839813Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 28939813Smckusick if (vp->v_usecount > 1 || mfsp->mfs_buflist) 29039438Smckusick panic("mfs_close"); 29139019Smckusick /* 29239019Smckusick * Send a request to the filesystem server to exit. 29339019Smckusick */ 29439389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 29539019Smckusick wakeup((caddr_t)vp); 29639019Smckusick return (0); 29739019Smckusick } 29839019Smckusick 29939019Smckusick /* 30039389Smckusick * Memory filesystem inactive routine 30139389Smckusick */ 30239389Smckusick /* ARGSUSED */ 303*51477Sbostic int 30448038Smckusick mfs_inactive(vp, p) 30539389Smckusick struct vnode *vp; 30648038Smckusick struct proc *p; 30739389Smckusick { 30839389Smckusick 30939389Smckusick if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 31039389Smckusick panic("mfs_inactive: not inactive"); 31139389Smckusick return (0); 31239389Smckusick } 31339389Smckusick 31439389Smckusick /* 31539677Smckusick * Print out the contents of an mfsnode. 31639677Smckusick */ 317*51477Sbostic int 31839677Smckusick mfs_print(vp) 31939677Smckusick struct vnode *vp; 32039677Smckusick { 32139677Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 32239677Smckusick 32339677Smckusick printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 32439677Smckusick mfsp->mfs_baseoff, mfsp->mfs_size); 325*51477Sbostic return (0); 32639677Smckusick } 32739677Smckusick 32839677Smckusick /* 32939019Smckusick * Block device bad operation 33039019Smckusick */ 331*51477Sbostic int 33239019Smckusick mfs_badop() 33339019Smckusick { 33439019Smckusick 33539389Smckusick panic("mfs_badop called\n"); 33639389Smckusick /* NOTREACHED */ 33739019Smckusick } 33839019Smckusick 33939019Smckusick /* 34039019Smckusick * Memory based filesystem initialization. 34139019Smckusick */ 34239019Smckusick mfs_init() 34339019Smckusick { 34439019Smckusick 34551035Sralph #if !defined(hp300) && !defined(i386) && !defined(mips) 34639019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 34741536Smckusick #endif 34839019Smckusick } 349