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