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