1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)mfs_vnops.c 7.16 (Berkeley) 06/22/90 18 */ 19 20 #include "param.h" 21 #include "time.h" 22 #include "kernel.h" 23 #include "proc.h" 24 #include "user.h" 25 #include "buf.h" 26 #include "vmmac.h" 27 #include "errno.h" 28 #include "map.h" 29 #include "vnode.h" 30 #include "../ufs/mfsnode.h" 31 #include "../ufs/mfsiom.h" 32 #include "machine/vmparam.h" 33 #include "machine/pte.h" 34 #include "machine/mtpr.h" 35 36 #if !defined(hp300) 37 static int mfsmap_want; /* 1 => need kernel I/O resources */ 38 struct map mfsmap[MFS_MAPSIZE]; 39 extern char mfsiobuf[]; 40 #endif 41 42 /* 43 * mfs vnode operations. 44 */ 45 int mfs_open(), 46 mfs_strategy(), 47 mfs_bmap(), 48 mfs_ioctl(), 49 mfs_close(), 50 mfs_inactive(), 51 mfs_print(), 52 mfs_badop(), 53 mfs_nullop(); 54 55 struct vnodeops mfs_vnodeops = { 56 mfs_badop, /* lookup */ 57 mfs_badop, /* create */ 58 mfs_badop, /* mknod */ 59 mfs_open, /* open */ 60 mfs_close, /* close */ 61 mfs_badop, /* access */ 62 mfs_badop, /* getattr */ 63 mfs_badop, /* setattr */ 64 mfs_badop, /* read */ 65 mfs_badop, /* write */ 66 mfs_ioctl, /* ioctl */ 67 mfs_badop, /* select */ 68 mfs_badop, /* mmap */ 69 mfs_badop, /* fsync */ 70 mfs_badop, /* seek */ 71 mfs_badop, /* remove */ 72 mfs_badop, /* link */ 73 mfs_badop, /* rename */ 74 mfs_badop, /* mkdir */ 75 mfs_badop, /* rmdir */ 76 mfs_badop, /* symlink */ 77 mfs_badop, /* readdir */ 78 mfs_badop, /* readlink */ 79 mfs_badop, /* abortop */ 80 mfs_inactive, /* inactive */ 81 mfs_nullop, /* reclaim */ 82 mfs_nullop, /* lock */ 83 mfs_nullop, /* unlock */ 84 mfs_bmap, /* bmap */ 85 mfs_strategy, /* strategy */ 86 mfs_print, /* print */ 87 mfs_nullop, /* islocked */ 88 }; 89 90 /* 91 * Vnode Operations. 92 * 93 * Open called to allow memory filesystem to initialize and 94 * validate before actual IO. Record our process identifier 95 * so we can tell when we are doing I/O to ourself. 96 */ 97 /* ARGSUSED */ 98 mfs_open(vp, mode, cred) 99 register struct vnode *vp; 100 int mode; 101 struct ucred *cred; 102 { 103 104 if (vp->v_type != VBLK) { 105 panic("mfs_ioctl not VBLK"); 106 /* NOTREACHED */ 107 } 108 return (0); 109 } 110 111 /* 112 * Ioctl operation. 113 */ 114 /* ARGSUSED */ 115 mfs_ioctl(vp, com, data, fflag, cred) 116 struct vnode *vp; 117 int com; 118 caddr_t data; 119 int fflag; 120 struct ucred *cred; 121 { 122 123 return (-1); 124 } 125 126 /* 127 * Pass I/O requests to the memory filesystem process. 128 */ 129 mfs_strategy(bp) 130 register struct buf *bp; 131 { 132 register struct mfsnode *mfsp; 133 struct vnode *vp; 134 135 if (vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0) 136 panic("mfs_strategy: bad dev"); 137 mfsp = VTOMFS(vp); 138 if (mfsp->mfs_pid == u.u_procp->p_pid) { 139 mfs_doio(bp, mfsp->mfs_baseoff); 140 } else { 141 bp->av_forw = mfsp->mfs_buflist; 142 mfsp->mfs_buflist = bp; 143 wakeup((caddr_t)vp); 144 } 145 return (0); 146 } 147 148 #if defined(vax) || defined(tahoe) 149 /* 150 * Memory file system I/O. 151 * 152 * Essentially play ubasetup() and disk interrupt service routine by 153 * doing the copies to or from the memfs process. If doing physio 154 * (i.e. pagein), we must map the I/O through the kernel virtual 155 * address space. 156 */ 157 mfs_doio(bp, base) 158 register struct buf *bp; 159 caddr_t base; 160 { 161 register struct pte *pte, *ppte; 162 register caddr_t vaddr; 163 int off, npf, npf2, reg; 164 caddr_t kernaddr, offset; 165 166 /* 167 * For phys I/O, map the b_addr into kernel virtual space using 168 * the Mfsiomap pte's. 169 */ 170 if ((bp->b_flags & B_PHYS) == 0) { 171 kernaddr = bp->b_un.b_addr; 172 } else { 173 if (bp->b_flags & (B_PAGET | B_UAREA | B_DIRTY)) 174 panic("swap on memfs?"); 175 off = (int)bp->b_un.b_addr & PGOFSET; 176 npf = btoc(bp->b_bcount + off); 177 /* 178 * Get some mapping page table entries 179 */ 180 while ((reg = rmalloc(mfsmap, (long)npf)) == 0) { 181 mfsmap_want++; 182 sleep((caddr_t)&mfsmap_want, PZERO-1); 183 } 184 reg--; 185 pte = vtopte(bp->b_proc, btop(bp->b_un.b_addr)); 186 /* 187 * Do vmaccess() but with the Mfsiomap page table. 188 */ 189 ppte = &Mfsiomap[reg]; 190 vaddr = &mfsiobuf[reg * NBPG]; 191 kernaddr = vaddr + off; 192 for (npf2 = npf; npf2; npf2--) { 193 mapin(ppte, (u_int)vaddr, pte->pg_pfnum, 194 (int)(PG_V|PG_KW)); 195 #if defined(tahoe) 196 if ((bp->b_flags & B_READ) == 0) 197 mtpr(P1DC, vaddr); 198 #endif 199 ppte++; 200 pte++; 201 vaddr += NBPG; 202 } 203 } 204 offset = base + (bp->b_blkno << DEV_BSHIFT); 205 if (bp->b_flags & B_READ) 206 bp->b_error = copyin(offset, kernaddr, bp->b_bcount); 207 else 208 bp->b_error = copyout(kernaddr, offset, bp->b_bcount); 209 if (bp->b_error) 210 bp->b_flags |= B_ERROR; 211 /* 212 * Release pte's used by physical I/O. 213 */ 214 if (bp->b_flags & B_PHYS) { 215 rmfree(mfsmap, (long)npf, (long)++reg); 216 if (mfsmap_want) { 217 mfsmap_want = 0; 218 wakeup((caddr_t)&mfsmap_want); 219 } 220 } 221 biodone(bp); 222 } 223 #endif /* vax || tahoe */ 224 225 #if defined(hp300) 226 /* 227 * Memory file system I/O. 228 * 229 * Trivial on the HP since buffer has already been mapping into KVA space. 230 */ 231 mfs_doio(bp, base) 232 register struct buf *bp; 233 caddr_t base; 234 { 235 base += (bp->b_blkno << DEV_BSHIFT); 236 if (bp->b_flags & B_READ) 237 bp->b_error = copyin(base, bp->b_un.b_addr, bp->b_bcount); 238 else 239 bp->b_error = copyout(bp->b_un.b_addr, base, bp->b_bcount); 240 if (bp->b_error) 241 bp->b_flags |= B_ERROR; 242 biodone(bp); 243 } 244 #endif 245 246 /* 247 * This is a noop, simply returning what one has been given. 248 */ 249 mfs_bmap(vp, bn, vpp, bnp) 250 struct vnode *vp; 251 daddr_t bn; 252 struct vnode **vpp; 253 daddr_t *bnp; 254 { 255 256 if (vpp != NULL) 257 *vpp = vp; 258 if (bnp != NULL) 259 *bnp = bn; 260 return (0); 261 } 262 263 /* 264 * Memory filesystem close routine 265 */ 266 /* ARGSUSED */ 267 mfs_close(vp, flag, cred) 268 register struct vnode *vp; 269 int flag; 270 struct ucred *cred; 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 mfs_inactive(vp) 312 struct vnode *vp; 313 { 314 315 if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1)) 316 panic("mfs_inactive: not inactive"); 317 return (0); 318 } 319 320 /* 321 * Print out the contents of an mfsnode. 322 */ 323 mfs_print(vp) 324 struct vnode *vp; 325 { 326 register struct mfsnode *mfsp = VTOMFS(vp); 327 328 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid, 329 mfsp->mfs_baseoff, mfsp->mfs_size); 330 } 331 332 /* 333 * Block device bad operation 334 */ 335 mfs_badop() 336 { 337 338 panic("mfs_badop called\n"); 339 /* NOTREACHED */ 340 } 341 342 /* 343 * Block device null operation 344 */ 345 mfs_nullop() 346 { 347 348 return (0); 349 } 350 351 /* 352 * Memory based filesystem initialization. 353 */ 354 mfs_init() 355 { 356 357 #if !defined(hp300) 358 rminit(mfsmap, (long)MFS_MAPREG, (long)1, "mfs mapreg", MFS_MAPSIZE); 359 #endif 360 } 361