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