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