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