1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $Id: $ 34 */ 35 36 #include "sys/param.h" 37 #include "sys/mount.h" 38 #include "sys/file.h" 39 #include "sys/errno.h" 40 #include "proc.h" 41 #include "buf.h" 42 #include "uio.h" 43 #include "malloc.h" 44 45 #include "vnode.h" 46 #include "iso.h" 47 #include "isofs_node.h" 48 #include "iso_rrip.h" 49 #include "ufs_dinode.h" /* XXX */ 50 51 #include "prototypes.h" 52 53 #define INOHSZ 512 54 #if ((INOHSZ&(INOHSZ-1)) == 0) 55 #define INOHASH(dev,ino) (((dev)+(ino))&(INOHSZ-1)) 56 #else 57 #define INOHASH(dev,ino) (((unsigned)((dev)+(ino)))%INOHSZ) 58 #endif 59 60 union iso_ihead { 61 union iso_ihead *ih_head[2]; 62 struct iso_node *ih_chain[2]; 63 } iso_ihead[INOHSZ]; 64 65 66 /* 67 * Initialize hash links for inodes. 68 */ 69 isofs_init() 70 { 71 register int i; 72 register union iso_ihead *ih = iso_ihead; 73 74 #ifndef lint 75 if (VN_MAXPRIVATE < sizeof(struct iso_node)) 76 panic("ihinit: too small"); 77 #endif /* not lint */ 78 for (i = INOHSZ; --i >= 0; ih++) { 79 ih->ih_head[0] = ih; 80 ih->ih_head[1] = ih; 81 } 82 } 83 84 /* 85 * Look up a ISOFS dinode number to find its incore vnode. 86 * If it is not in core, read it in from the specified device. 87 * If it is in core, wait for the lock bit to clear, then 88 * return the inode locked. Detection and handling of mount 89 * points must be done by the calling routine. 90 */ 91 iso_iget(xp, ino, ipp, isodir) 92 struct iso_node *xp; 93 ino_t ino; 94 struct iso_node **ipp; 95 struct iso_directory_record *isodir; 96 { 97 dev_t dev = xp->i_dev; 98 struct mount *mntp = ITOV(xp)->v_mount; 99 extern struct vnodeops isofs_vnodeops, spec_isonodeops; 100 register struct iso_node *ip, *iq; 101 register struct vnode *vp; 102 struct vnode *nvp; 103 struct buf *bp; 104 struct dinode *dp; 105 union iso_ihead *ih; 106 int i, error, result; 107 struct iso_mnt *imp; 108 109 ih = &iso_ihead[INOHASH(dev, ino)]; 110 loop: 111 for (ip = ih->ih_chain[0]; 112 ip != (struct iso_node *)ih; 113 ip = ip->i_forw) { 114 if (ino != ip->i_number || dev != ip->i_dev) 115 continue; 116 if ((ip->i_flag&ILOCKED) != 0) { 117 ip->i_flag |= IWANT; 118 tsleep((caddr_t)ip, PINOD, "isoget", 0); 119 goto loop; 120 } 121 if (vget(ITOV(ip))) 122 goto loop; 123 *ipp = ip; 124 return(0); 125 } 126 /* 127 * Allocate a new inode. 128 */ 129 #define VT_ISOFS (VT_MFS+1) 130 if (error = getnewvnode(VT_ISOFS, mntp, &isofs_vnodeops, &nvp)) { 131 *ipp = 0; 132 return (error); 133 } 134 ip = VTOI(nvp); 135 ip->i_vnode = nvp; 136 ip->i_flag = 0; 137 ip->i_devvp = 0; 138 ip->i_diroff = 0; 139 ip->iso_parent = xp->i_diroff; /* Parent directory's */ 140 ip->iso_parent_ext = xp->iso_extent; 141 ip->i_lockf = 0; 142 /* 143 * Put it onto its hash chain and lock it so that other requests for 144 * this inode will block if they arrive while we are sleeping waiting 145 * for old data structures to be purged or for the contents of the 146 * disk portion of this inode to be read. 147 */ 148 ip->i_dev = dev; 149 ip->i_number = ino; 150 insque(ip, ih); 151 ISO_ILOCK(ip); 152 153 ip->iso_reclen = isonum_711 (isodir->length); 154 ip->iso_extlen = isonum_711 (isodir->ext_attr_length); 155 ip->iso_extent = isonum_733 (isodir->extent); 156 ip->i_size = isonum_733 (isodir->size); 157 ip->iso_flags = isonum_711 (isodir->flags); 158 ip->iso_unit_size = isonum_711 (isodir->file_unit_size); 159 ip->iso_interleave_gap = isonum_711 (isodir->interleave); 160 ip->iso_volume_seq = isonum_723 (isodir->volume_sequence_number); 161 ip->iso_namelen = isonum_711 (isodir->name_len); 162 163 imp = VFSTOISOFS (mntp); 164 vp = ITOV(ip); 165 ip->inode.iso_mode = 0; 166 ip->inode.iso_dev = 0; 167 result = 0; 168 169 /* 170 * Setup time stamp, attribute , if CL or PL, set loc but not yet.. 171 */ 172 switch ( imp->iso_ftype ) { 173 case ISO_FTYPE_9660: 174 isofs_rrip_defattr ( isodir, &(ip->inode) ); 175 isofs_rrip_deftstamp( isodir, &(ip->inode) ); 176 goto FlameOff; 177 break; 178 case ISO_FTYPE_RRIP: 179 result = isofs_rrip_analyze( isodir, &(ip->inode) ); 180 break; 181 default: 182 printf("unknown iso_ftype.. %d\n", imp->iso_ftype ); 183 break; 184 } 185 #ifdef nope 186 if(ino == 6786446) { 187 /* printf("force console "); */ 188 ip->inode.iso_mode &= ~IFMT; 189 ip->inode.iso_mode |= IFCHR; 190 ip->inode.iso_dev = makedev(0,0); 191 result |= ISO_SUSP_DEVICE; 192 } 193 if(ino == 6790878) { 194 /* printf("force fd0a "); */ 195 ip->inode.iso_mode &= ~IFMT; 196 ip->inode.iso_mode |= IFBLK; 197 ip->inode.iso_dev = makedev(2,0); 198 result |= ISO_SUSP_DEVICE; 199 } 200 if(ino == 6979808) { 201 /* printf("force wd0a "); */ 202 ip->inode.iso_mode &= ~IFMT; 203 ip->inode.iso_mode |= IFBLK; 204 ip->inode.iso_dev = makedev(0,0); 205 result |= ISO_SUSP_DEVICE; 206 } 207 if(ino == 6981968) { 208 /* printf("force wd0b "); */ 209 ip->inode.iso_mode &= ~IFMT; 210 ip->inode.iso_mode |= IFBLK; 211 ip->inode.iso_dev = makedev(0,1); 212 result |= ISO_SUSP_DEVICE; 213 } 214 if(ino == 6782126) { 215 /* printf("force com1 "); */ 216 ip->inode.iso_mode &= ~IFMT; 217 ip->inode.iso_mode |= IFCHR; 218 ip->inode.iso_dev = makedev(8,1); 219 result |= ISO_SUSP_DEVICE; 220 } 221 if(ino == 6942836) { 222 /* printf("force tty "); */ 223 ip->inode.iso_mode &= ~IFMT; 224 ip->inode.iso_mode |= IFCHR; 225 ip->inode.iso_dev = makedev(1,0); 226 result |= ISO_SUSP_DEVICE; 227 } 228 229 if(ino == 6977650) { 230 /* printf("force vga "); */ 231 ip->inode.iso_mode &= ~IFMT; 232 ip->inode.iso_mode |= IFCHR; 233 ip->inode.iso_dev = makedev(12,0); 234 result |= ISO_SUSP_DEVICE; 235 } 236 if(ino == 6808336) { 237 /* printf("force kmem "); */ 238 ip->inode.iso_mode &= ~IFMT; 239 ip->inode.iso_mode |= IFCHR; 240 ip->inode.iso_dev = makedev(2,1); 241 result |= ISO_SUSP_DEVICE; 242 } 243 if(ino == 6834176) { 244 /* printf("force mem "); */ 245 ip->inode.iso_mode &= ~IFMT; 246 ip->inode.iso_mode |= IFCHR; 247 ip->inode.iso_dev = makedev(2,0); 248 result |= ISO_SUSP_DEVICE; 249 } 250 if(ino == 6836334) { 251 /* printf("force null "); */ 252 ip->inode.iso_mode &= ~IFMT; 253 ip->inode.iso_mode |= IFCHR; 254 ip->inode.iso_dev = makedev(2,2); 255 result |= ISO_SUSP_DEVICE; 256 } 257 if(ino == 6927476) { 258 /* printf("force rwd0d "); */ 259 ip->inode.iso_mode &= ~IFMT; 260 ip->inode.iso_mode |= IFCHR; 261 ip->inode.iso_dev = makedev(3,3); 262 result |= ISO_SUSP_DEVICE; 263 } 264 if(ino == 6920990) { 265 /* printf("force rwd0a "); */ 266 ip->inode.iso_mode &= ~IFMT; 267 ip->inode.iso_mode |= IFCHR; 268 ip->inode.iso_dev = makedev(3,0); 269 result |= ISO_SUSP_DEVICE; 270 } 271 #endif 272 273 274 if ((ip->inode.iso_mode & IFMT) == IFBLK) 275 vp->v_type = VBLK; 276 else 277 if ((ip->inode.iso_mode & IFMT) == IFCHR) 278 vp->v_type = VCHR; 279 else { 280 FlameOff: 281 if (ip->iso_flags & 2) { 282 vp->v_type = VDIR; 283 } else { 284 vp->v_type = VREG; 285 } 286 } 287 288 /* 289 * Initialize the associated vnode 290 */ 291 if ( result & ISO_SUSP_SLINK ) { 292 char symname[NAME_MAX]; 293 int symlen; 294 295 vp->v_type = VLNK; /* Symbolic Link */ 296 isofs_rrip_getsymname(vp, isodir, symname, &symlen); 297 ip->i_size = symlen; 298 /*printf("SL%d mode %x ", symlen, ip->inode.iso_mode);*/ 299 } 300 if ( result & ISO_SUSP_DEVICE ) { 301 vp->v_op = &spec_isonodeops; 302 if (nvp = checkalias(vp, ip->inode.iso_dev, mntp)) { 303 /* 304 * Reinitialize aliased inode. 305 */ 306 vp = nvp; 307 iq = VTOI(vp); 308 iq->i_vnode = vp; 309 iq->i_flag = 0; 310 ISO_ILOCK(iq); 311 iq->inode = ip->inode; 312 iq->i_dev = dev; 313 iq->i_number = ino; 314 insque(iq, ih); 315 /* 316 * Discard unneeded vnode 317 */ 318 iso_iput(ip); 319 ip = iq; 320 } 321 } 322 323 imp = VFSTOISOFS (mntp); 324 325 if (ino == iso_lblktosize(imp, imp->root_extent)) 326 vp->v_flag |= VROOT; 327 /* 328 * Finish inode initialization. 329 */ 330 ip->i_mnt = imp; 331 ip->i_devvp = imp->im_devvp; 332 VREF(ip->i_devvp); 333 *ipp = ip; 334 return (0); 335 } 336 337 /* 338 * Unlock and decrement the reference count of an inode structure. 339 */ 340 iso_iput(ip) 341 register struct iso_node *ip; 342 { 343 344 if ((ip->i_flag & ILOCKED) == 0) 345 panic("iso_iput"); 346 ISO_IUNLOCK(ip); 347 vrele(ITOV(ip)); 348 } 349 350 /* 351 * Last reference to an inode, write the inode out and if necessary, 352 * truncate and deallocate the file. 353 */ 354 isofs_inactive(vp, p) 355 struct vnode *vp; 356 struct proc *p; 357 { 358 register struct iso_node *ip = VTOI(vp); 359 int mode, error = 0; 360 extern int prtactive; 361 362 #ifdef DEBUG 363 if (prtactive && vp->v_usecount != 0) 364 vprint("isofs_inactive: pushing active", vp); 365 #endif 366 367 ip->i_flag = 0; 368 /* 369 * If we are done with the inode, reclaim it 370 * so that it can be reused immediately. 371 */ 372 373 /* 374 * Purge symlink entries since they cause problems 375 * when cached. Leave other entries alone since flushing 376 * them every time is a major performance hit. 377 */ 378 if (vp->v_usecount == 0 && vp->v_type == VLNK) { 379 /* printf("Flushing symlink entry\n");*/ 380 vgone(vp); 381 } 382 return (error); 383 } 384 385 /* 386 * Reclaim an inode so that it can be used for other purposes. 387 */ 388 isofs_reclaim(vp) 389 register struct vnode *vp; 390 { 391 register struct iso_node *ip = VTOI(vp); 392 int i; 393 extern int prtactive; 394 395 #ifdef DEBUG 396 if (prtactive && vp->v_usecount != 0) 397 vprint("isofs_reclaim: pushing active", vp); 398 #endif 399 /* 400 * Remove the inode from its hash chain. 401 */ 402 remque(ip); 403 ip->i_forw = ip; 404 ip->i_back = ip; 405 /* 406 * Purge old data structures associated with the inode. 407 */ 408 cache_purge(vp); 409 if (ip->i_devvp) { 410 vrele(ip->i_devvp); 411 ip->i_devvp = 0; 412 } 413 ip->i_flag = 0; 414 return (0); 415 } 416 417 /* 418 * Lock an inode. If its already locked, set the WANT bit and sleep. 419 */ 420 iso_ilock(ip) 421 register struct iso_node *ip; 422 { 423 424 while (ip->i_flag & ILOCKED) { 425 ip->i_flag |= IWANT; 426 if (ip->i_spare0 == curproc->p_pid) 427 panic("locking against myself"); 428 ip->i_spare1 = curproc->p_pid; 429 (void) tsleep((caddr_t)ip, PINOD, "isolck", 0); 430 } 431 ip->i_spare1 = 0; 432 ip->i_spare0 = curproc->p_pid; 433 ip->i_flag |= ILOCKED; 434 } 435 436 /* 437 * Unlock an inode. If WANT bit is on, wakeup. 438 */ 439 iso_iunlock(ip) 440 register struct iso_node *ip; 441 { 442 443 #ifdef DEBUG 444 if ((ip->i_flag & ILOCKED) == 0) 445 vprint("iso_iunlock: unlocked inode", ITOV(ip)); 446 #endif 447 ip->i_spare0 = 0; 448 ip->i_flag &= ~ILOCKED; 449 if (ip->i_flag&IWANT) { 450 ip->i_flag &= ~IWANT; 451 wakeup((caddr_t)ip); 452 } 453 } 454