139019Smckusick /* 239019Smckusick * Copyright (c) 1989 The Regents of the University of California. 339019Smckusick * All rights reserved. 439019Smckusick * 539019Smckusick * Redistribution and use in source and binary forms are permitted 639019Smckusick * provided that the above copyright notice and this paragraph are 739019Smckusick * duplicated in all such forms and that any documentation, 839019Smckusick * advertising materials, and other materials related to such 939019Smckusick * distribution and use acknowledge that the software was developed 1039019Smckusick * by the University of California, Berkeley. The name of the 1139019Smckusick * University may not be used to endorse or promote products derived 1239019Smckusick * from this software without specific prior written permission. 1339019Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1439019Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1539019Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1639019Smckusick * 17*41536Smckusick * @(#)mfs_vnops.c 7.15 (Berkeley) 05/10/90 1839019Smckusick */ 1939019Smckusick 2039019Smckusick #include "param.h" 2139019Smckusick #include "time.h" 2239357Smckusick #include "kernel.h" 2339019Smckusick #include "proc.h" 2439357Smckusick #include "user.h" 2539019Smckusick #include "buf.h" 2639019Smckusick #include "vmmac.h" 2739019Smckusick #include "errno.h" 2839019Smckusick #include "map.h" 2939019Smckusick #include "vnode.h" 3039389Smckusick #include "../ufs/mfsnode.h" 3139019Smckusick #include "../ufs/mfsiom.h" 3239456Smckusick #include "machine/vmparam.h" 3339456Smckusick #include "machine/pte.h" 3439456Smckusick #include "machine/mtpr.h" 3539019Smckusick 36*41536Smckusick #if !defined(hp300) 3739019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 3839019Smckusick struct map mfsmap[MFS_MAPSIZE]; 3939019Smckusick extern char mfsiobuf[]; 40*41536Smckusick #endif 4139019Smckusick 4239019Smckusick /* 4339019Smckusick * mfs vnode operations. 4439019Smckusick */ 4539019Smckusick int mfs_open(), 4639019Smckusick mfs_strategy(), 4739680Smckusick mfs_bmap(), 4839019Smckusick mfs_ioctl(), 4939019Smckusick mfs_close(), 5039389Smckusick mfs_inactive(), 5139677Smckusick mfs_print(), 5239019Smckusick mfs_badop(), 5339019Smckusick mfs_nullop(); 5439019Smckusick 5539019Smckusick struct vnodeops mfs_vnodeops = { 5639677Smckusick mfs_badop, /* lookup */ 5739677Smckusick mfs_badop, /* create */ 5839677Smckusick mfs_badop, /* mknod */ 5939677Smckusick mfs_open, /* open */ 6039677Smckusick mfs_close, /* close */ 6139677Smckusick mfs_badop, /* access */ 6239677Smckusick mfs_badop, /* getattr */ 6339677Smckusick mfs_badop, /* setattr */ 6439677Smckusick mfs_badop, /* read */ 6539677Smckusick mfs_badop, /* write */ 6639677Smckusick mfs_ioctl, /* ioctl */ 6739677Smckusick mfs_badop, /* select */ 6839677Smckusick mfs_badop, /* mmap */ 6939677Smckusick mfs_badop, /* fsync */ 7039677Smckusick mfs_badop, /* seek */ 7139677Smckusick mfs_badop, /* remove */ 7239677Smckusick mfs_badop, /* link */ 7339677Smckusick mfs_badop, /* rename */ 7439677Smckusick mfs_badop, /* mkdir */ 7539677Smckusick mfs_badop, /* rmdir */ 7639677Smckusick mfs_badop, /* symlink */ 7739677Smckusick mfs_badop, /* readdir */ 7839677Smckusick mfs_badop, /* readlink */ 7939677Smckusick mfs_badop, /* abortop */ 8039677Smckusick mfs_inactive, /* inactive */ 8139677Smckusick mfs_nullop, /* reclaim */ 8239852Smckusick mfs_nullop, /* lock */ 8339852Smckusick mfs_nullop, /* unlock */ 8439680Smckusick mfs_bmap, /* bmap */ 8539677Smckusick mfs_strategy, /* strategy */ 8639677Smckusick mfs_print, /* print */ 8739910Smckusick mfs_nullop, /* islocked */ 8839019Smckusick }; 8939019Smckusick 9039019Smckusick /* 9139019Smckusick * Vnode Operations. 9239019Smckusick * 9339019Smckusick * Open called to allow memory filesystem to initialize and 9439357Smckusick * validate before actual IO. Record our process identifier 9539357Smckusick * so we can tell when we are doing I/O to ourself. 9639019Smckusick */ 9739019Smckusick /* ARGSUSED */ 9839019Smckusick mfs_open(vp, mode, cred) 9939019Smckusick register struct vnode *vp; 10039019Smckusick int mode; 10139019Smckusick struct ucred *cred; 10239019Smckusick { 10339019Smckusick 10439019Smckusick if (vp->v_type != VBLK) { 10539019Smckusick panic("mfs_ioctl not VBLK"); 10639019Smckusick /* NOTREACHED */ 10739019Smckusick } 10839019Smckusick return (0); 10939019Smckusick } 11039019Smckusick 11139019Smckusick /* 11239019Smckusick * Ioctl operation. 11339019Smckusick */ 11439019Smckusick /* ARGSUSED */ 11539019Smckusick mfs_ioctl(vp, com, data, fflag, cred) 11639019Smckusick struct vnode *vp; 11739019Smckusick int com; 11839019Smckusick caddr_t data; 11939019Smckusick int fflag; 12039019Smckusick struct ucred *cred; 12139019Smckusick { 12239019Smckusick 12339019Smckusick return (-1); 12439019Smckusick } 12539019Smckusick 12639019Smckusick /* 12739019Smckusick * Pass I/O requests to the memory filesystem process. 12839019Smckusick */ 12939019Smckusick mfs_strategy(bp) 13039019Smckusick register struct buf *bp; 13139019Smckusick { 13239822Smckusick register struct mfsnode *mfsp; 13339822Smckusick struct vnode *vp; 13439019Smckusick 13539822Smckusick if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 13639822Smckusick panic("mfs_strategy: bad dev"); 13739822Smckusick mfsp = VTOMFS(vp); 13839389Smckusick if (mfsp->mfs_pid == u.u_procp->p_pid) { 13939389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 14039019Smckusick } else { 14139389Smckusick bp->av_forw = mfsp->mfs_buflist; 14239389Smckusick mfsp->mfs_buflist = bp; 14339822Smckusick wakeup((caddr_t)vp); 14439019Smckusick } 14539357Smckusick return (0); 14639019Smckusick } 14739019Smckusick 14839019Smckusick /* 14939019Smckusick * Memory file system I/O. 15039019Smckusick * 15139019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 15239019Smckusick * doing the copies to or from the memfs process. If doing physio 15339019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 15439019Smckusick * address space. 15539019Smckusick */ 15639019Smckusick mfs_doio(bp, base) 15739019Smckusick register struct buf *bp; 15839019Smckusick caddr_t base; 15939019Smckusick { 160*41536Smckusick #if !defined(hp300) 16139019Smckusick register struct pte *pte, *ppte; 16239019Smckusick register caddr_t vaddr; 16339019Smckusick int off, npf, npf2, reg; 164*41536Smckusick #endif 16539019Smckusick caddr_t kernaddr, offset; 16639019Smckusick 167*41536Smckusick #if defined(hp300) 168*41536Smckusick kernaddr = bp->b_un.b_addr; 169*41536Smckusick #else 17039019Smckusick /* 17139019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 17239019Smckusick * the Mfsiomap pte's. 17339019Smckusick */ 17439019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 17539019Smckusick kernaddr = bp->b_un.b_addr; 17639019Smckusick } else { 17739019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 17839019Smckusick panic("swap on memfs?"); 17939019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 18039019Smckusick npf = btoc(bp->b_bcount + off); 18139019Smckusick /* 18239019Smckusick * Get some mapping page table entries 18339019Smckusick */ 18439019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 18539019Smckusick mfsmap_want++; 18639019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 18739019Smckusick } 18839019Smckusick reg--; 18939019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 19039019Smckusick /* 19139019Smckusick * Do vmaccess() but with the Mfsiomap page table. 19239019Smckusick */ 19339019Smckusick ppte = &Mfsiomap[reg]; 19439019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 19539019Smckusick kernaddr = vaddr + off; 19639019Smckusick for (npf2 = npf; npf2; npf2--) { 19739019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 19839019Smckusick (int)(PG_V|PG_KW)); 19939019Smckusick #if defined(tahoe) 20039019Smckusick if ((bp->b_flags & B_READ) == 0) 20139019Smckusick mtpr(P1DC, vaddr); 20239019Smckusick #endif 20339019Smckusick ppte++; 20439019Smckusick pte++; 20539019Smckusick vaddr += NBPG; 20639019Smckusick } 20739019Smckusick } 208*41536Smckusick #endif /* !defined(hp300) */ 20939019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 21039019Smckusick if (bp->b_flags & B_READ) 21139019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 21239019Smckusick else 21339019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 21439019Smckusick if (bp->b_error) 21539019Smckusick bp->b_flags |= B_ERROR; 216*41536Smckusick #if !defined(hp300) 21739019Smckusick /* 21839019Smckusick * Release pte's used by physical I/O. 21939019Smckusick */ 22039019Smckusick if (bp->b_flags & B_PHYS) { 22139019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 22239019Smckusick if (mfsmap_want) { 22339019Smckusick mfsmap_want = 0; 22439019Smckusick wakeup((caddr_t)&mfsmap_want); 22539019Smckusick } 22639019Smckusick } 227*41536Smckusick #endif 22839019Smckusick biodone(bp); 22939019Smckusick } 23039019Smckusick 23139019Smckusick /* 23239680Smckusick * This is a noop, simply returning what one has been given. 23339680Smckusick */ 23439680Smckusick mfs_bmap(vp, bn, vpp, bnp) 23539680Smckusick struct vnode *vp; 23639680Smckusick daddr_t bn; 23739680Smckusick struct vnode **vpp; 23839680Smckusick daddr_t *bnp; 23939680Smckusick { 24039680Smckusick 24139680Smckusick if (vpp != NULL) 24239680Smckusick *vpp = vp; 24339680Smckusick if (bnp != NULL) 24439680Smckusick *bnp = bn; 24539680Smckusick return (0); 24639680Smckusick } 24739680Smckusick 24839680Smckusick /* 24939019Smckusick * Memory filesystem close routine 25039019Smckusick */ 25139019Smckusick /* ARGSUSED */ 25239019Smckusick mfs_close(vp, flag, cred) 25339019Smckusick register struct vnode *vp; 25439019Smckusick int flag; 25539019Smckusick struct ucred *cred; 25639019Smckusick { 25739389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 25839438Smckusick register struct buf *bp; 25939019Smckusick 26039019Smckusick /* 26139438Smckusick * Finish any pending I/O requests. 26239438Smckusick */ 26339438Smckusick while (bp = mfsp->mfs_buflist) { 26439438Smckusick mfsp->mfs_buflist = bp->av_forw; 26539438Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 26639438Smckusick wakeup((caddr_t)bp); 26739438Smckusick } 26839438Smckusick /* 26939019Smckusick * On last close of a memory filesystem 27039019Smckusick * we must invalidate any in core blocks, so that 27139019Smckusick * we can, free up its vnode. 27239019Smckusick */ 27339677Smckusick vflushbuf(vp, 0); 27439677Smckusick if (vinvalbuf(vp, 1)) 27539019Smckusick return (0); 27639019Smckusick /* 27739438Smckusick * There should be no way to have any more uses of this 27839438Smckusick * vnode, so if we find any other uses, it is a panic. 27939019Smckusick */ 28039813Smckusick if (vp->v_usecount > 1) 28139813Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 28239813Smckusick if (vp->v_usecount > 1 || mfsp->mfs_buflist) 28339438Smckusick panic("mfs_close"); 28439019Smckusick /* 28539019Smckusick * Send a request to the filesystem server to exit. 28639019Smckusick */ 28739389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 28839019Smckusick wakeup((caddr_t)vp); 28939019Smckusick return (0); 29039019Smckusick } 29139019Smckusick 29239019Smckusick /* 29339389Smckusick * Memory filesystem inactive routine 29439389Smckusick */ 29539389Smckusick /* ARGSUSED */ 29639389Smckusick mfs_inactive(vp) 29739389Smckusick struct vnode *vp; 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 * Block device null operation 32939019Smckusick */ 33039019Smckusick mfs_nullop() 33139019Smckusick { 33239019Smckusick 33339019Smckusick return (0); 33439019Smckusick } 33539019Smckusick 33639019Smckusick /* 33739019Smckusick * Memory based filesystem initialization. 33839019Smckusick */ 33939019Smckusick mfs_init() 34039019Smckusick { 34139019Smckusick 342*41536Smckusick #if !defined(hp300) 34339019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 344*41536Smckusick #endif 34539019Smckusick } 346