1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)mfs_vnops.c 8.5 (Berkeley) 07/28/94 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_pathconf_desc, mfs_pathconf }, /* pathconf */ 73 { &vop_advlock_desc, mfs_advlock }, /* advlock */ 74 { &vop_blkatoff_desc, mfs_blkatoff }, /* blkatoff */ 75 { &vop_valloc_desc, mfs_valloc }, /* valloc */ 76 { &vop_vfree_desc, mfs_vfree }, /* vfree */ 77 { &vop_truncate_desc, mfs_truncate }, /* truncate */ 78 { &vop_update_desc, mfs_update }, /* update */ 79 { &vop_bwrite_desc, mfs_bwrite }, /* bwrite */ 80 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 81 }; 82 struct vnodeopv_desc mfs_vnodeop_opv_desc = 83 { &mfs_vnodeop_p, mfs_vnodeop_entries }; 84 85 /* 86 * Vnode Operations. 87 * 88 * Open called to allow memory filesystem to initialize and 89 * validate before actual IO. Record our process identifier 90 * so we can tell when we are doing I/O to ourself. 91 */ 92 /* ARGSUSED */ 93 int 94 mfs_open(ap) 95 struct vop_open_args /* { 96 struct vnode *a_vp; 97 int a_mode; 98 struct ucred *a_cred; 99 struct proc *a_p; 100 } */ *ap; 101 { 102 103 if (ap->a_vp->v_type != VBLK) { 104 panic("mfs_ioctl not VBLK"); 105 /* NOTREACHED */ 106 } 107 return (0); 108 } 109 110 /* 111 * Ioctl operation. 112 */ 113 /* ARGSUSED */ 114 int 115 mfs_ioctl(ap) 116 struct vop_ioctl_args /* { 117 struct vnode *a_vp; 118 int a_command; 119 caddr_t a_data; 120 int a_fflag; 121 struct ucred *a_cred; 122 struct proc *a_p; 123 } */ *ap; 124 { 125 126 return (ENOTTY); 127 } 128 129 /* 130 * Pass I/O requests to the memory filesystem process. 131 */ 132 int 133 mfs_strategy(ap) 134 struct vop_strategy_args /* { 135 struct buf *a_bp; 136 } */ *ap; 137 { 138 register struct buf *bp = ap->a_bp; 139 register struct mfsnode *mfsp; 140 struct vnode *vp; 141 struct proc *p = curproc; /* XXX */ 142 143 if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 144 panic("mfs_strategy: bad dev"); 145 mfsp = VTOMFS(vp); 146 /* check for mini-root access */ 147 if (mfsp->mfs_pid == 0) { 148 caddr_t base; 149 150 base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT); 151 if (bp->b_flags & B_READ) 152 bcopy(base, bp->b_data, bp->b_bcount); 153 else 154 bcopy(bp->b_data, base, bp->b_bcount); 155 biodone(bp); 156 } else if (mfsp->mfs_pid == p->p_pid) { 157 mfs_doio(bp, mfsp->mfs_baseoff); 158 } else { 159 bp->b_actf = mfsp->mfs_buflist; 160 mfsp->mfs_buflist = bp; 161 wakeup((caddr_t)vp); 162 } 163 return (0); 164 } 165 166 #if defined(vax) || defined(tahoe) 167 /* 168 * Memory file system I/O. 169 * 170 * Essentially play ubasetup() and disk interrupt service routine by 171 * doing the copies to or from the memfs process. If doing physio 172 * (i.e. pagein), we must map the I/O through the kernel virtual 173 * address space. 174 */ 175 void 176 mfs_doio(bp, base) 177 register struct buf *bp; 178 caddr_t base; 179 { 180 register struct pte *pte, *ppte; 181 register caddr_t vaddr; 182 int off, npf, npf2, reg; 183 caddr_t kernaddr, offset; 184 185 /* 186 * For phys I/O, map the b_data into kernel virtual space using 187 * the Mfsiomap pte's. 188 */ 189 if ((bp->b_flags & B_PHYS) == 0) { 190 kernaddr = bp->b_data; 191 } else { 192 if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 193 panic("swap on memfs?"); 194 off = (int)bp->b_data & PGOFSET; 195 npf = btoc(bp->b_bcount + off); 196 /* 197 * Get some mapping page table entries 198 */ 199 while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 200 mfsmap_want++; 201 sleep((caddr_t)&mfsmap_want, PZERO-1); 202 } 203 reg--; 204 pte = vtopte(bp->b_proc, btop(bp->b_data)); 205 /* 206 * Do vmaccess() but with the Mfsiomap page table. 207 */ 208 ppte = &Mfsiomap[reg]; 209 vaddr = &mfsiobuf[reg * NBPG]; 210 kernaddr = vaddr + off; 211 for (npf2 = npf; npf2; npf2--) { 212 mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 213 (int)(PG_V|PG_KW)); 214 #if defined(tahoe) 215 if ((bp->b_flags & B_READ) == 0) 216 mtpr(P1DC, vaddr); 217 #endif 218 ppte++; 219 pte++; 220 vaddr += NBPG; 221 } 222 } 223 offset = base + (bp->b_blkno << DEV_BSHIFT); 224 if (bp->b_flags & B_READ) 225 bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 226 else 227 bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 228 if (bp->b_error) 229 bp->b_flags |= B_ERROR; 230 /* 231 * Release pte's used by physical I/O. 232 */ 233 if (bp->b_flags & B_PHYS) { 234 rmfree(mfsmap, (long)npf, (long)++reg); 235 if (mfsmap_want) { 236 mfsmap_want = 0; 237 wakeup((caddr_t)&mfsmap_want); 238 } 239 } 240 biodone(bp); 241 } 242 #endif /* vax || tahoe */ 243 244 #if defined(hp300) || defined(i386) || defined(mips) || defined(sparc) || defined(luna68k) 245 /* 246 * Memory file system I/O. 247 * 248 * Trivial on the HP since buffer has already been mapping into KVA space. 249 */ 250 void 251 mfs_doio(bp, base) 252 register struct buf *bp; 253 caddr_t base; 254 { 255 256 base += (bp->b_blkno << DEV_BSHIFT); 257 if (bp->b_flags & B_READ) 258 bp->b_error = copyin(base, bp->b_data, bp->b_bcount); 259 else 260 bp->b_error = copyout(bp->b_data, base, bp->b_bcount); 261 if (bp->b_error) 262 bp->b_flags |= B_ERROR; 263 biodone(bp); 264 } 265 #endif 266 267 /* 268 * This is a noop, simply returning what one has been given. 269 */ 270 int 271 mfs_bmap(ap) 272 struct vop_bmap_args /* { 273 struct vnode *a_vp; 274 daddr_t a_bn; 275 struct vnode **a_vpp; 276 daddr_t *a_bnp; 277 int *a_runp; 278 } */ *ap; 279 { 280 281 if (ap->a_vpp != NULL) 282 *ap->a_vpp = ap->a_vp; 283 if (ap->a_bnp != NULL) 284 *ap->a_bnp = ap->a_bn; 285 return (0); 286 } 287 288 /* 289 * Memory filesystem close routine 290 */ 291 /* ARGSUSED */ 292 int 293 mfs_close(ap) 294 struct vop_close_args /* { 295 struct vnode *a_vp; 296 int a_fflag; 297 struct ucred *a_cred; 298 struct proc *a_p; 299 } */ *ap; 300 { 301 register struct vnode *vp = ap->a_vp; 302 register struct mfsnode *mfsp = VTOMFS(vp); 303 register struct buf *bp; 304 int error; 305 306 /* 307 * Finish any pending I/O requests. 308 */ 309 while (bp = mfsp->mfs_buflist) { 310 mfsp->mfs_buflist = bp->b_actf; 311 mfs_doio(bp, mfsp->mfs_baseoff); 312 wakeup((caddr_t)bp); 313 } 314 /* 315 * On last close of a memory filesystem 316 * we must invalidate any in core blocks, so that 317 * we can, free up its vnode. 318 */ 319 if (error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0)) 320 return (error); 321 /* 322 * There should be no way to have any more uses of this 323 * vnode, so if we find any other uses, it is a panic. 324 */ 325 if (vp->v_usecount > 1) 326 printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 327 if (vp->v_usecount > 1 || mfsp->mfs_buflist) 328 panic("mfs_close"); 329 /* 330 * Send a request to the filesystem server to exit. 331 */ 332 mfsp->mfs_buflist = (struct buf *)(-1); 333 wakeup((caddr_t)vp); 334 return (0); 335 } 336 337 /* 338 * Memory filesystem inactive routine 339 */ 340 /* ARGSUSED */ 341 int 342 mfs_inactive(ap) 343 struct vop_inactive_args /* { 344 struct vnode *a_vp; 345 } */ *ap; 346 { 347 register struct mfsnode *mfsp = VTOMFS(ap->a_vp); 348 349 if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1)) 350 panic("mfs_inactive: not inactive (mfs_buflist %x)", 351 mfsp->mfs_buflist); 352 return (0); 353 } 354 355 /* 356 * Reclaim a memory filesystem devvp so that it can be reused. 357 */ 358 int 359 mfs_reclaim(ap) 360 struct vop_reclaim_args /* { 361 struct vnode *a_vp; 362 } */ *ap; 363 { 364 register struct vnode *vp = ap->a_vp; 365 366 FREE(vp->v_data, M_MFSNODE); 367 vp->v_data = NULL; 368 return (0); 369 } 370 371 /* 372 * Print out the contents of an mfsnode. 373 */ 374 int 375 mfs_print(ap) 376 struct vop_print_args /* { 377 struct vnode *a_vp; 378 } */ *ap; 379 { 380 register struct mfsnode *mfsp = VTOMFS(ap->a_vp); 381 382 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 383 mfsp->mfs_baseoff, mfsp->mfs_size); 384 return (0); 385 } 386 387 /* 388 * Block device bad operation 389 */ 390 int 391 mfs_badop() 392 { 393 394 panic("mfs_badop called\n"); 395 /* NOTREACHED */ 396 } 397 398 /* 399 * Memory based filesystem initialization. 400 */ 401 mfs_init() 402 { 403 404 #if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k) 405 rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 406 #endif 407 } 408