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.1 (Berkeley) 06/11/93 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->b_actf = 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 int *a_runp; 277 } */ *ap; 278 { 279 280 if (ap->a_vpp != NULL) 281 *ap->a_vpp = ap->a_vp; 282 if (ap->a_bnp != NULL) 283 *ap->a_bnp = ap->a_bn; 284 return (0); 285 } 286 287 /* 288 * Memory filesystem close routine 289 */ 290 /* ARGSUSED */ 291 int 292 mfs_close(ap) 293 struct vop_close_args /* { 294 struct vnode *a_vp; 295 int a_fflag; 296 struct ucred *a_cred; 297 struct proc *a_p; 298 } */ *ap; 299 { 300 register struct vnode *vp = ap->a_vp; 301 register struct mfsnode *mfsp = VTOMFS(vp); 302 register struct buf *bp; 303 int error; 304 305 /* 306 * Finish any pending I/O requests. 307 */ 308 while (bp = mfsp->mfs_buflist) { 309 mfsp->mfs_buflist = bp->b_actf; 310 mfs_doio(bp, mfsp->mfs_baseoff); 311 wakeup((caddr_t)bp); 312 } 313 /* 314 * On last close of a memory filesystem 315 * we must invalidate any in core blocks, so that 316 * we can, free up its vnode. 317 */ 318 if (error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0)) 319 return (error); 320 /* 321 * There should be no way to have any more uses of this 322 * vnode, so if we find any other uses, it is a panic. 323 */ 324 if (vp->v_usecount > 1) 325 printf("mfs_close: ref count %d > 1\n", vp->v_usecount); 326 if (vp->v_usecount > 1 || mfsp->mfs_buflist) 327 panic("mfs_close"); 328 /* 329 * Send a request to the filesystem server to exit. 330 */ 331 mfsp->mfs_buflist = (struct buf *)(-1); 332 wakeup((caddr_t)vp); 333 return (0); 334 } 335 336 /* 337 * Memory filesystem inactive routine 338 */ 339 /* ARGSUSED */ 340 int 341 mfs_inactive(ap) 342 struct vop_inactive_args /* { 343 struct vnode *a_vp; 344 } */ *ap; 345 { 346 register struct mfsnode *mfsp = VTOMFS(ap->a_vp); 347 348 if (mfsp->mfs_buflist && mfsp->mfs_buflist != (struct buf *)(-1)) 349 panic("mfs_inactive: not inactive (mfs_buflist %x)", 350 mfsp->mfs_buflist); 351 return (0); 352 } 353 354 /* 355 * Reclaim a memory filesystem devvp so that it can be reused. 356 */ 357 int 358 mfs_reclaim(ap) 359 struct vop_reclaim_args /* { 360 struct vnode *a_vp; 361 } */ *ap; 362 { 363 364 FREE(ap->a_vp->v_data, M_MFSNODE); 365 ap->a_vp->v_data = NULL; 366 return (0); 367 } 368 369 /* 370 * Print out the contents of an mfsnode. 371 */ 372 int 373 mfs_print(ap) 374 struct vop_print_args /* { 375 struct vnode *a_vp; 376 } */ *ap; 377 { 378 register struct mfsnode *mfsp = VTOMFS(ap->a_vp); 379 380 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 381 mfsp->mfs_baseoff, mfsp->mfs_size); 382 return (0); 383 } 384 385 /* 386 * Block device bad operation 387 */ 388 int 389 mfs_badop() 390 { 391 392 panic("mfs_badop called\n"); 393 /* NOTREACHED */ 394 } 395 396 /* 397 * Memory based filesystem initialization. 398 */ 399 mfs_init() 400 { 401 402 #if !defined(hp300) && !defined(i386) && !defined(mips) && !defined(sparc) && !defined(luna68k) 403 rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 404 #endif 405 } 406