139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 544536Sbostic * %sccs.include.redist.c% 639019Smckusick * 7*51570Smckusick * @(#)mfs_vnops.c 7.25 (Berkeley) 11/05/91 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> 1847571Skarels 1951477Sbostic #include <machine/vmparam.h> 2051477Sbostic #include <machine/mtpr.h> 2147571Skarels 2251477Sbostic #include <ufs/mfs/mfsnode.h> 2351477Sbostic #include <ufs/mfs/mfsiom.h> 2451477Sbostic #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 */ 69*51570Smckusick mfs_blkatoff, /* blkatoff */ 70*51570Smckusick mfs_vget, /* vget */ 71*51570Smckusick mfs_valloc, /* valloc */ 72*51570Smckusick mfs_vfree, /* vfree */ 73*51570Smckusick mfs_truncate, /* truncate */ 74*51570Smckusick mfs_update, /* update */ 75*51570Smckusick mfs_bwrite, /* bwrite */ 7639019Smckusick }; 7739019Smckusick 7839019Smckusick /* 7939019Smckusick * Vnode Operations. 8039019Smckusick * 8139019Smckusick * Open called to allow memory filesystem to initialize and 8239357Smckusick * validate before actual IO. Record our process identifier 8339357Smckusick * so we can tell when we are doing I/O to ourself. 8439019Smckusick */ 8539019Smckusick /* ARGSUSED */ 8651477Sbostic int 8748038Smckusick mfs_open(vp, mode, cred, p) 8839019Smckusick register struct vnode *vp; 8939019Smckusick int mode; 9039019Smckusick struct ucred *cred; 9148038Smckusick struct proc *p; 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 */ 10551477Sbostic int 10648038Smckusick mfs_ioctl(vp, com, data, fflag, cred, p) 10739019Smckusick struct vnode *vp; 10839019Smckusick int com; 10939019Smckusick caddr_t data; 11039019Smckusick int fflag; 11139019Smckusick struct ucred *cred; 11248038Smckusick struct proc *p; 11339019Smckusick { 11439019Smckusick 11539019Smckusick return (-1); 11639019Smckusick } 11739019Smckusick 11839019Smckusick /* 11939019Smckusick * Pass I/O requests to the memory filesystem process. 12039019Smckusick */ 12151477Sbostic int 12239019Smckusick mfs_strategy(bp) 12339019Smckusick register struct buf *bp; 12439019Smckusick { 12539822Smckusick register struct mfsnode *mfsp; 12639822Smckusick struct vnode *vp; 12748038Smckusick struct proc *p = curproc; /* XXX */ 12839019Smckusick 12939822Smckusick if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 13039822Smckusick panic("mfs_strategy: bad dev"); 13139822Smckusick mfsp = VTOMFS(vp); 13248038Smckusick if (mfsp->mfs_pid == p->p_pid) { 13339389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 13439019Smckusick } else { 13539389Smckusick bp->av_forw = mfsp->mfs_buflist; 13639389Smckusick mfsp->mfs_buflist = bp; 13739822Smckusick wakeup((caddr_t)vp); 13839019Smckusick } 13939357Smckusick return (0); 14039019Smckusick } 14139019Smckusick 14243412Shibler #if defined(vax) || defined(tahoe) 14339019Smckusick /* 14439019Smckusick * Memory file system I/O. 14539019Smckusick * 14639019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 14739019Smckusick * doing the copies to or from the memfs process. If doing physio 14839019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 14939019Smckusick * address space. 15039019Smckusick */ 15151477Sbostic void 15239019Smckusick mfs_doio(bp, base) 15339019Smckusick register struct buf *bp; 15439019Smckusick caddr_t base; 15539019Smckusick { 15639019Smckusick register struct pte *pte, *ppte; 15739019Smckusick register caddr_t vaddr; 15839019Smckusick int off, npf, npf2, reg; 15939019Smckusick caddr_t kernaddr, offset; 16039019Smckusick 16139019Smckusick /* 16239019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 16339019Smckusick * the Mfsiomap pte's. 16439019Smckusick */ 16539019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 16639019Smckusick kernaddr = bp->b_un.b_addr; 16739019Smckusick } else { 16839019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 16939019Smckusick panic("swap on memfs?"); 17039019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 17139019Smckusick npf = btoc(bp->b_bcount + off); 17239019Smckusick /* 17339019Smckusick * Get some mapping page table entries 17439019Smckusick */ 17539019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 17639019Smckusick mfsmap_want++; 17739019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 17839019Smckusick } 17939019Smckusick reg--; 18039019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 18139019Smckusick /* 18239019Smckusick * Do vmaccess() but with the Mfsiomap page table. 18339019Smckusick */ 18439019Smckusick ppte = &Mfsiomap[reg]; 18539019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 18639019Smckusick kernaddr = vaddr + off; 18739019Smckusick for (npf2 = npf; npf2; npf2--) { 18839019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 18939019Smckusick (int)(PG_V|PG_KW)); 19039019Smckusick #if defined(tahoe) 19139019Smckusick if ((bp->b_flags & B_READ) == 0) 19239019Smckusick mtpr(P1DC, vaddr); 19339019Smckusick #endif 19439019Smckusick ppte++; 19539019Smckusick pte++; 19639019Smckusick vaddr += NBPG; 19739019Smckusick } 19839019Smckusick } 19939019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 20039019Smckusick if (bp->b_flags & B_READ) 20139019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 20239019Smckusick else 20339019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 20439019Smckusick if (bp->b_error) 20539019Smckusick bp->b_flags |= B_ERROR; 20639019Smckusick /* 20739019Smckusick * Release pte's used by physical I/O. 20839019Smckusick */ 20939019Smckusick if (bp->b_flags & B_PHYS) { 21039019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 21139019Smckusick if (mfsmap_want) { 21239019Smckusick mfsmap_want = 0; 21339019Smckusick wakeup((caddr_t)&mfsmap_want); 21439019Smckusick } 21539019Smckusick } 21639019Smckusick biodone(bp); 21739019Smckusick } 21843412Shibler #endif /* vax || tahoe */ 21939019Smckusick 22051035Sralph #if defined(hp300) || defined(i386) || defined(mips) 22139019Smckusick /* 22243412Shibler * Memory file system I/O. 22343412Shibler * 22443412Shibler * Trivial on the HP since buffer has already been mapping into KVA space. 22543412Shibler */ 22651477Sbostic void 22743412Shibler mfs_doio(bp, base) 22843412Shibler register struct buf *bp; 22943412Shibler caddr_t base; 23043412Shibler { 23143412Shibler base += (bp->b_blkno << DEV_BSHIFT); 23243412Shibler if (bp->b_flags & B_READ) 23343412Shibler bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 23443412Shibler else 23543412Shibler bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 23643412Shibler if (bp->b_error) 23743412Shibler bp->b_flags |= B_ERROR; 23843412Shibler biodone(bp); 23943412Shibler } 24043412Shibler #endif 24143412Shibler 24243412Shibler /* 24339680Smckusick * This is a noop, simply returning what one has been given. 24439680Smckusick */ 24551477Sbostic int 24639680Smckusick mfs_bmap(vp, bn, vpp, bnp) 24739680Smckusick struct vnode *vp; 24839680Smckusick daddr_t bn; 24939680Smckusick struct vnode **vpp; 25039680Smckusick daddr_t *bnp; 25139680Smckusick { 25239680Smckusick 25339680Smckusick if (vpp != NULL) 25439680Smckusick *vpp = vp; 25539680Smckusick if (bnp != NULL) 25639680Smckusick *bnp = bn; 25739680Smckusick return (0); 25839680Smckusick } 25939680Smckusick 26039680Smckusick /* 26139019Smckusick * Memory filesystem close routine 26239019Smckusick */ 26339019Smckusick /* ARGSUSED */ 26451477Sbostic int 26548038Smckusick mfs_close(vp, flag, cred, p) 26639019Smckusick register struct vnode *vp; 26739019Smckusick int flag; 26839019Smckusick struct ucred *cred; 26948038Smckusick struct proc *p; 27039019Smckusick { 27139389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 27239438Smckusick register struct buf *bp; 27339019Smckusick 27439019Smckusick /* 27539438Smckusick * Finish any pending I/O requests. 27639438Smckusick */ 27739438Smckusick while (bp = mfsp->mfs_buflist) { 27839438Smckusick mfsp->mfs_buflist = bp->av_forw; 27939438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 28039438Smckusick wakeup((caddr_t)bp); 28139438Smckusick } 28239438Smckusick /* 28339019Smckusick * On last close of a memory filesystem 28439019Smckusick * we must invalidate any in core blocks, so that 28539019Smckusick * we can, free up its vnode. 28639019Smckusick */ 28739677Smckusick vflushbuf(vp, 0); 28839677Smckusick if (vinvalbuf(vp, 1)) 28939019Smckusick return (0); 29039019Smckusick /* 29139438Smckusick * There should be no way to have any more uses of this 29239438Smckusick * vnode, so if we find any other uses, it is a panic. 29339019Smckusick */ 29439813Smckusick if (vp->v_usecount > 1) 29539813Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 29639813Smckusick if (vp->v_usecount > 1 || mfsp->mfs_buflist) 29739438Smckusick panic("mfs_close"); 29839019Smckusick /* 29939019Smckusick * Send a request to the filesystem server to exit. 30039019Smckusick */ 30139389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 30239019Smckusick wakeup((caddr_t)vp); 30339019Smckusick return (0); 30439019Smckusick } 30539019Smckusick 30639019Smckusick /* 30739389Smckusick * Memory filesystem inactive routine 30839389Smckusick */ 30939389Smckusick /* ARGSUSED */ 31051477Sbostic int 31148038Smckusick mfs_inactive(vp, p) 31239389Smckusick struct vnode *vp; 31348038Smckusick struct proc *p; 31439389Smckusick { 31539389Smckusick 31639389Smckusick if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 31739389Smckusick panic("mfs_inactive: not inactive"); 31839389Smckusick return (0); 31939389Smckusick } 32039389Smckusick 32139389Smckusick /* 32239677Smckusick * Print out the contents of an mfsnode. 32339677Smckusick */ 32451477Sbostic int 32539677Smckusick mfs_print(vp) 32639677Smckusick struct vnode *vp; 32739677Smckusick { 32839677Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 32939677Smckusick 33039677Smckusick printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 33139677Smckusick mfsp->mfs_baseoff, mfsp->mfs_size); 33251477Sbostic return (0); 33339677Smckusick } 33439677Smckusick 33539677Smckusick /* 33639019Smckusick * Block device bad operation 33739019Smckusick */ 33851477Sbostic int 33939019Smckusick mfs_badop() 34039019Smckusick { 34139019Smckusick 34239389Smckusick panic("mfs_badop called\n"); 34339389Smckusick /* NOTREACHED */ 34439019Smckusick } 34539019Smckusick 34639019Smckusick /* 34739019Smckusick * Memory based filesystem initialization. 34839019Smckusick */ 34939019Smckusick mfs_init() 35039019Smckusick { 35139019Smckusick 35251035Sralph #if !defined(hp300) && !defined(i386) && !defined(mips) 35339019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 35441536Smckusick #endif 35539019Smckusick } 356