1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)mfs_vnops.c 7.23 (Berkeley) 09/06/91 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "time.h" 13 #include "kernel.h" 14 #include "proc.h" 15 #include "buf.h" 16 #include "map.h" 17 #include "vnode.h" 18 19 #include "mfsnode.h" 20 #include "mfsiom.h" 21 22 #include "machine/vmparam.h" 23 #include "machine/mtpr.h" 24 25 #if !defined(hp300) && !defined(i386) && !defined(mips) 26 static int mfsmap_want; /* 1 => need kernel I/O resources */ 27 struct map mfsmap[MFS_MAPSIZE]; 28 extern char mfsiobuf[]; 29 #endif 30 31 /* 32 * mfs vnode operations. 33 */ 34 struct vnodeops mfs_vnodeops = { 35 mfs_lookup, /* lookup */ 36 mfs_create, /* create */ 37 mfs_mknod, /* mknod */ 38 mfs_open, /* open */ 39 mfs_close, /* close */ 40 mfs_access, /* access */ 41 mfs_getattr, /* getattr */ 42 mfs_setattr, /* setattr */ 43 mfs_read, /* read */ 44 mfs_write, /* write */ 45 mfs_ioctl, /* ioctl */ 46 mfs_select, /* select */ 47 mfs_mmap, /* mmap */ 48 mfs_fsync, /* fsync */ 49 mfs_seek, /* seek */ 50 mfs_remove, /* remove */ 51 mfs_link, /* link */ 52 mfs_rename, /* rename */ 53 mfs_mkdir, /* mkdir */ 54 mfs_rmdir, /* rmdir */ 55 mfs_symlink, /* symlink */ 56 mfs_readdir, /* readdir */ 57 mfs_readlink, /* readlink */ 58 mfs_abortop, /* abortop */ 59 mfs_inactive, /* inactive */ 60 mfs_reclaim, /* reclaim */ 61 mfs_lock, /* lock */ 62 mfs_unlock, /* unlock */ 63 mfs_bmap, /* bmap */ 64 mfs_strategy, /* strategy */ 65 mfs_print, /* print */ 66 mfs_islocked, /* islocked */ 67 mfs_advlock, /* advlock */ 68 }; 69 70 /* 71 * Vnode Operations. 72 * 73 * Open called to allow memory filesystem to initialize and 74 * validate before actual IO. Record our process identifier 75 * so we can tell when we are doing I/O to ourself. 76 */ 77 /* ARGSUSED */ 78 mfs_open(vp, mode, cred, p) 79 register struct vnode *vp; 80 int mode; 81 struct ucred *cred; 82 struct proc *p; 83 { 84 85 if (vp->v_type != VBLK) { 86 panic("mfs_ioctl not VBLK"); 87 /* NOTREACHED */ 88 } 89 return (0); 90 } 91 92 /* 93 * Ioctl operation. 94 */ 95 /* ARGSUSED */ 96 mfs_ioctl(vp, com, data, fflag, cred, p) 97 struct vnode *vp; 98 int com; 99 caddr_t data; 100 int fflag; 101 struct ucred *cred; 102 struct proc *p; 103 { 104 105 return (-1); 106 } 107 108 /* 109 * Pass I/O requests to the memory filesystem process. 110 */ 111 mfs_strategy(bp) 112 register struct buf *bp; 113 { 114 register struct mfsnode *mfsp; 115 struct vnode *vp; 116 struct proc *p = curproc; /* XXX */ 117 118 if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 119 panic("mfs_strategy: bad dev"); 120 mfsp = VTOMFS(vp); 121 if (mfsp->mfs_pid == p->p_pid) { 122 mfs_doio(bp, mfsp->mfs_baseoff); 123 } else { 124 bp->av_forw = mfsp->mfs_buflist; 125 mfsp->mfs_buflist = bp; 126 wakeup((caddr_t)vp); 127 } 128 return (0); 129 } 130 131 #if defined(vax) || defined(tahoe) 132 /* 133 * Memory file system I/O. 134 * 135 * Essentially play ubasetup() and disk interrupt service routine by 136 * doing the copies to or from the memfs process. If doing physio 137 * (i.e. pagein), we must map the I/O through the kernel virtual 138 * address space. 139 */ 140 mfs_doio(bp, base) 141 register struct buf *bp; 142 caddr_t base; 143 { 144 register struct pte *pte, *ppte; 145 register caddr_t vaddr; 146 int off, npf, npf2, reg; 147 caddr_t kernaddr, offset; 148 149 /* 150 * For phys I/O, map the b_addr into kernel virtual space using 151 * the Mfsiomap pte's. 152 */ 153 if ((bp->b_flags & B_PHYS) == 0) { 154 kernaddr = bp->b_un.b_addr; 155 } else { 156 if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 157 panic("swap on memfs?"); 158 off = (int)bp->b_un.b_addr & PGOFSET; 159 npf = btoc(bp->b_bcount + off); 160 /* 161 * Get some mapping page table entries 162 */ 163 while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 164 mfsmap_want++; 165 sleep((caddr_t)&mfsmap_want, PZERO-1); 166 } 167 reg--; 168 pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 169 /* 170 * Do vmaccess() but with the Mfsiomap page table. 171 */ 172 ppte = &Mfsiomap[reg]; 173 vaddr = &mfsiobuf[reg * NBPG]; 174 kernaddr = vaddr + off; 175 for (npf2 = npf; npf2; npf2--) { 176 mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 177 (int)(PG_V|PG_KW)); 178 #if defined(tahoe) 179 if ((bp->b_flags & B_READ) == 0) 180 mtpr(P1DC, vaddr); 181 #endif 182 ppte++; 183 pte++; 184 vaddr += NBPG; 185 } 186 } 187 offset = base + (bp->b_blkno << DEV_BSHIFT); 188 if (bp->b_flags & B_READ) 189 bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 190 else 191 bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 192 if (bp->b_error) 193 bp->b_flags |= B_ERROR; 194 /* 195 * Release pte's used by physical I/O. 196 */ 197 if (bp->b_flags & B_PHYS) { 198 rmfree(mfsmap, (long)npf, (long)++reg); 199 if (mfsmap_want) { 200 mfsmap_want = 0; 201 wakeup((caddr_t)&mfsmap_want); 202 } 203 } 204 biodone(bp); 205 } 206 #endif /* vax || tahoe */ 207 208 #if defined(hp300) || defined(i386) || defined(mips) 209 /* 210 * Memory file system I/O. 211 * 212 * Trivial on the HP since buffer has already been mapping into KVA space. 213 */ 214 mfs_doio(bp, base) 215 register struct buf *bp; 216 caddr_t base; 217 { 218 base += (bp->b_blkno << DEV_BSHIFT); 219 if (bp->b_flags & B_READ) 220 bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 221 else 222 bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 223 if (bp->b_error) 224 bp->b_flags |= B_ERROR; 225 biodone(bp); 226 } 227 #endif 228 229 /* 230 * This is a noop, simply returning what one has been given. 231 */ 232 mfs_bmap(vp, bn, vpp, bnp) 233 struct vnode *vp; 234 daddr_t bn; 235 struct vnode **vpp; 236 daddr_t *bnp; 237 { 238 239 if (vpp != NULL) 240 *vpp = vp; 241 if (bnp != NULL) 242 *bnp = bn; 243 return (0); 244 } 245 246 /* 247 * Memory filesystem close routine 248 */ 249 /* ARGSUSED */ 250 mfs_close(vp, flag, cred, p) 251 register struct vnode *vp; 252 int flag; 253 struct ucred *cred; 254 struct proc *p; 255 { 256 register struct mfsnode *mfsp = VTOMFS(vp); 257 register struct buf *bp; 258 259 /* 260 * Finish any pending I/O requests. 261 */ 262 while (bp = mfsp->mfs_buflist) { 263 mfsp->mfs_buflist = bp->av_forw; 264 mfs_doio(bp, mfsp->mfs_baseoff); 265 wakeup((caddr_t)bp); 266 } 267 /* 268 * On last close of a memory filesystem 269 * we must invalidate any in core blocks, so that 270 * we can, free up its vnode. 271 */ 272 vflushbuf(vp, 0); 273 if (vinvalbuf(vp, 1)) 274 return (0); 275 /* 276 * There should be no way to have any more uses of this 277 * vnode, so if we find any other uses, it is a panic. 278 */ 279 if (vp->v_usecount > 1) 280 printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 281 if (vp->v_usecount > 1 || mfsp->mfs_buflist) 282 panic("mfs_close"); 283 /* 284 * Send a request to the filesystem server to exit. 285 */ 286 mfsp->mfs_buflist = (struct buf *)(-1); 287 wakeup((caddr_t)vp); 288 return (0); 289 } 290 291 /* 292 * Memory filesystem inactive routine 293 */ 294 /* ARGSUSED */ 295 mfs_inactive(vp, p) 296 struct vnode *vp; 297 struct proc *p; 298 { 299 300 if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 301 panic("mfs_inactive: not inactive"); 302 return (0); 303 } 304 305 /* 306 * Print out the contents of an mfsnode. 307 */ 308 mfs_print(vp) 309 struct vnode *vp; 310 { 311 register struct mfsnode *mfsp = VTOMFS(vp); 312 313 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 314 mfsp->mfs_baseoff, mfsp->mfs_size); 315 } 316 317 /* 318 * Block device bad operation 319 */ 320 mfs_badop() 321 { 322 323 panic("mfs_badop called\n"); 324 /* NOTREACHED */ 325 } 326 327 /* 328 * Memory based filesystem initialization. 329 */ 330 mfs_init() 331 { 332 333 #if !defined(hp300) && !defined(i386) && !defined(mips) 334 rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 335 #endif 336 } 337