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*39389Smckusick * @(#)mfs_vnops.c 7.4 (Berkeley) 10/24/89 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" 30*39389Smckusick #include "../ufs/mfsnode.h" 3139019Smckusick #include "../ufs/mfsiom.h" 3239019Smckusick #include "../machine/vmparam.h" 3339019Smckusick #include "../machine/pte.h" 3439019Smckusick #include "../machine/mtpr.h" 3539019Smckusick 3639019Smckusick static int mfsmap_want; /* 1 => need kernel I/O resources */ 3739019Smckusick struct map mfsmap[MFS_MAPSIZE]; 3839019Smckusick extern char mfsiobuf[]; 3939019Smckusick 4039019Smckusick /* 4139019Smckusick * mfs vnode operations. 4239019Smckusick */ 4339019Smckusick int mfs_open(), 4439019Smckusick mfs_strategy(), 4539019Smckusick mfs_ioctl(), 4639019Smckusick mfs_close(), 47*39389Smckusick mfs_inactive(), 4839019Smckusick mfs_badop(), 4939019Smckusick mfs_nullop(); 5039019Smckusick 5139019Smckusick struct vnodeops mfs_vnodeops = { 5239019Smckusick mfs_badop, 5339019Smckusick mfs_badop, 5439019Smckusick mfs_badop, 5539019Smckusick mfs_open, 5639019Smckusick mfs_close, 5739019Smckusick mfs_badop, 5839019Smckusick mfs_badop, 5939019Smckusick mfs_badop, 6039019Smckusick mfs_badop, 6139019Smckusick mfs_badop, 6239019Smckusick mfs_ioctl, 6339019Smckusick mfs_badop, 6439019Smckusick mfs_badop, 6539019Smckusick mfs_badop, 6639019Smckusick mfs_badop, 6739019Smckusick mfs_badop, 6839019Smckusick mfs_badop, 6939019Smckusick mfs_badop, 7039019Smckusick mfs_badop, 7139019Smckusick mfs_badop, 7239019Smckusick mfs_badop, 7339019Smckusick mfs_badop, 7439019Smckusick mfs_badop, 7539019Smckusick mfs_badop, 76*39389Smckusick mfs_inactive, 77*39389Smckusick mfs_nullop, 7839019Smckusick mfs_badop, 7939019Smckusick mfs_badop, 8039019Smckusick mfs_badop, 8139019Smckusick mfs_strategy, 8239019Smckusick }; 8339019Smckusick 8439019Smckusick /* 8539019Smckusick * Vnode Operations. 8639019Smckusick * 8739019Smckusick * Open called to allow memory filesystem to initialize and 8839357Smckusick * validate before actual IO. Record our process identifier 8939357Smckusick * so we can tell when we are doing I/O to ourself. 9039019Smckusick */ 9139019Smckusick /* ARGSUSED */ 9239019Smckusick mfs_open(vp, mode, cred) 9339019Smckusick register struct vnode *vp; 9439019Smckusick int mode; 9539019Smckusick struct ucred *cred; 9639019Smckusick { 9739019Smckusick 9839019Smckusick if (vp->v_type != VBLK) { 9939019Smckusick panic("mfs_ioctl not VBLK"); 10039019Smckusick /* NOTREACHED */ 10139019Smckusick } 10239019Smckusick return (0); 10339019Smckusick } 10439019Smckusick 10539019Smckusick /* 10639019Smckusick * Ioctl operation. 10739019Smckusick */ 10839019Smckusick /* ARGSUSED */ 10939019Smckusick mfs_ioctl(vp, com, data, fflag, cred) 11039019Smckusick struct vnode *vp; 11139019Smckusick int com; 11239019Smckusick caddr_t data; 11339019Smckusick int fflag; 11439019Smckusick struct ucred *cred; 11539019Smckusick { 11639019Smckusick 11739019Smckusick return (-1); 11839019Smckusick } 11939019Smckusick 12039019Smckusick /* 12139019Smckusick * Pass I/O requests to the memory filesystem process. 12239019Smckusick */ 12339019Smckusick mfs_strategy(bp) 12439019Smckusick register struct buf *bp; 12539019Smckusick { 126*39389Smckusick register struct mfsnode *mfsp = VTOMFS(bp->b_vp); 12739019Smckusick 128*39389Smckusick if (mfsp->mfs_pid == u.u_procp->p_pid) { 129*39389Smckusick mfs_doio(bp, mfsp->mfs_baseoff); 13039019Smckusick } else { 131*39389Smckusick bp->av_forw = mfsp->mfs_buflist; 132*39389Smckusick mfsp->mfs_buflist = bp; 13339019Smckusick wakeup((caddr_t)bp->b_vp); 13439019Smckusick } 13539357Smckusick return (0); 13639019Smckusick } 13739019Smckusick 13839019Smckusick /* 13939019Smckusick * Memory file system I/O. 14039019Smckusick * 14139019Smckusick * Essentially play ubasetup() and disk interrupt service routine by 14239019Smckusick * doing the copies to or from the memfs process. If doing physio 14339019Smckusick * (i.e. pagein), we must map the I/O through the kernel virtual 14439019Smckusick * address space. 14539019Smckusick */ 14639019Smckusick mfs_doio(bp, base) 14739019Smckusick register struct buf *bp; 14839019Smckusick caddr_t base; 14939019Smckusick { 15039019Smckusick register struct pte *pte, *ppte; 15139019Smckusick register caddr_t vaddr; 15239019Smckusick int off, npf, npf2, reg; 15339019Smckusick caddr_t kernaddr, offset; 15439019Smckusick 15539019Smckusick /* 15639019Smckusick * For phys I/O, map the b_addr into kernel virtual space using 15739019Smckusick * the Mfsiomap pte's. 15839019Smckusick */ 15939019Smckusick if ((bp->b_flags & B_PHYS) == 0) { 16039019Smckusick kernaddr = bp->b_un.b_addr; 16139019Smckusick } else { 16239019Smckusick if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 16339019Smckusick panic("swap on memfs?"); 16439019Smckusick off = (int)bp->b_un.b_addr & PGOFSET; 16539019Smckusick npf = btoc(bp->b_bcount + off); 16639019Smckusick /* 16739019Smckusick * Get some mapping page table entries 16839019Smckusick */ 16939019Smckusick while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 17039019Smckusick mfsmap_want++; 17139019Smckusick sleep((caddr_t)&mfsmap_want, PZERO-1); 17239019Smckusick } 17339019Smckusick reg--; 17439019Smckusick pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 17539019Smckusick /* 17639019Smckusick * Do vmaccess() but with the Mfsiomap page table. 17739019Smckusick */ 17839019Smckusick ppte = &Mfsiomap[reg]; 17939019Smckusick vaddr = &mfsiobuf[reg * NBPG]; 18039019Smckusick kernaddr = vaddr + off; 18139019Smckusick for (npf2 = npf; npf2; npf2--) { 18239019Smckusick mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 18339019Smckusick (int)(PG_V|PG_KW)); 18439019Smckusick #if defined(tahoe) 18539019Smckusick if ((bp->b_flags & B_READ) == 0) 18639019Smckusick mtpr(P1DC, vaddr); 18739019Smckusick #endif 18839019Smckusick ppte++; 18939019Smckusick pte++; 19039019Smckusick vaddr += NBPG; 19139019Smckusick } 19239019Smckusick } 19339019Smckusick offset = base + (bp->b_blkno << DEV_BSHIFT); 19439019Smckusick if (bp->b_flags & B_READ) 19539019Smckusick bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 19639019Smckusick else 19739019Smckusick bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 19839019Smckusick if (bp->b_error) 19939019Smckusick bp->b_flags |= B_ERROR; 20039019Smckusick /* 20139019Smckusick * Release pte's used by physical I/O. 20239019Smckusick */ 20339019Smckusick if (bp->b_flags & B_PHYS) { 20439019Smckusick rmfree(mfsmap, (long)npf, (long)++reg); 20539019Smckusick if (mfsmap_want) { 20639019Smckusick mfsmap_want = 0; 20739019Smckusick wakeup((caddr_t)&mfsmap_want); 20839019Smckusick } 20939019Smckusick } 21039019Smckusick biodone(bp); 21139019Smckusick } 21239019Smckusick 21339019Smckusick /* 21439019Smckusick * Memory filesystem close routine 21539019Smckusick */ 21639019Smckusick /* ARGSUSED */ 21739019Smckusick mfs_close(vp, flag, cred) 21839019Smckusick register struct vnode *vp; 21939019Smckusick int flag; 22039019Smckusick struct ucred *cred; 22139019Smckusick { 222*39389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 22339019Smckusick 22439019Smckusick /* 22539019Smckusick * On last close of a memory filesystem 22639019Smckusick * we must invalidate any in core blocks, so that 22739019Smckusick * we can, free up its vnode. 22839019Smckusick */ 22939019Smckusick bflush(vp->v_mount); 23039019Smckusick if (binval(vp->v_mount)) 23139019Smckusick return (0); 23239019Smckusick /* 23339019Smckusick * We don't want to really close the device if it is still 23439019Smckusick * in use. Since every use (buffer, inode, swap, cmap) 23539019Smckusick * holds a reference to the vnode, and because we ensure 23639019Smckusick * that there cannot be more than one vnode per device, 23739019Smckusick * we need only check that we are down to the last 23839019Smckusick * reference before closing. 23939019Smckusick */ 24039019Smckusick if (vp->v_count > 1) { 24139019Smckusick printf("mfs_close: ref count %d > 1\n", vp->v_count); 24239019Smckusick return (0); 24339019Smckusick } 24439019Smckusick /* 24539019Smckusick * Send a request to the filesystem server to exit. 24639019Smckusick */ 247*39389Smckusick while (mfsp->mfs_buflist) 24839357Smckusick sleep(&lbolt); 249*39389Smckusick mfsp->mfs_buflist = (struct buf *)(-1); 25039019Smckusick wakeup((caddr_t)vp); 25139019Smckusick return (0); 25239019Smckusick } 25339019Smckusick 25439019Smckusick /* 255*39389Smckusick * Memory filesystem inactive routine 256*39389Smckusick */ 257*39389Smckusick /* ARGSUSED */ 258*39389Smckusick mfs_inactive(vp) 259*39389Smckusick struct vnode *vp; 260*39389Smckusick { 261*39389Smckusick 262*39389Smckusick if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 263*39389Smckusick panic("mfs_inactive: not inactive"); 264*39389Smckusick vp->v_type = VNON; 265*39389Smckusick return (0); 266*39389Smckusick } 267*39389Smckusick 268*39389Smckusick /* 26939019Smckusick * Block device bad operation 27039019Smckusick */ 27139019Smckusick mfs_badop() 27239019Smckusick { 27339019Smckusick 274*39389Smckusick panic("mfs_badop called\n"); 275*39389Smckusick /* NOTREACHED */ 27639019Smckusick } 27739019Smckusick 27839019Smckusick /* 27939019Smckusick * Block device null operation 28039019Smckusick */ 28139019Smckusick mfs_nullop() 28239019Smckusick { 28339019Smckusick 28439019Smckusick return (0); 28539019Smckusick } 28639019Smckusick 28739019Smckusick /* 28839019Smckusick * Memory based filesystem initialization. 28939019Smckusick */ 29039019Smckusick mfs_init() 29139019Smckusick { 29239019Smckusick 29339019Smckusick rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 29439019Smckusick } 295