1 /*- 2 * Copyright (c) 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * %sccs.include.redist.c% 11 * 12 * @(#)cd9660_vfsops.c 8.10 (Berkeley) 03/30/95 13 */ 14 15 #include <sys/param.h> 16 #include <sys/systm.h> 17 #include <sys/namei.h> 18 #include <sys/proc.h> 19 #include <sys/kernel.h> 20 #include <sys/vnode.h> 21 #include <miscfs/specfs/specdev.h> 22 #include <sys/mount.h> 23 #include <sys/buf.h> 24 #include <sys/file.h> 25 #include <sys/dkbad.h> 26 #include <sys/disklabel.h> 27 #include <sys/ioctl.h> 28 #include <sys/errno.h> 29 #include <sys/malloc.h> 30 #include <sys/stat.h> 31 32 #include <isofs/cd9660/iso.h> 33 #include <isofs/cd9660/cd9660_node.h> 34 #include <isofs/cd9660/cd9660_mount.h> 35 36 extern int enodev (); 37 38 struct vfsops cd9660_vfsops = { 39 cd9660_mount, 40 cd9660_start, 41 cd9660_unmount, 42 cd9660_root, 43 cd9660_quotactl, 44 cd9660_statfs, 45 cd9660_sync, 46 cd9660_vget, 47 cd9660_fhtovp, 48 cd9660_vptofh, 49 cd9660_init, 50 cd9660_sysctl 51 }; 52 53 /* 54 * Called by vfs_mountroot when iso is going to be mounted as root. 55 * 56 * Name is updated by mount(8) after booting. 57 */ 58 #define ROOTNAME "root_device" 59 60 static iso_mountfs(); 61 62 cd9660_mountroot() 63 { 64 register struct mount *mp; 65 extern struct vnode *rootvp; 66 struct proc *p = curproc; /* XXX */ 67 struct iso_mnt *imp; 68 register struct fs *fs; 69 u_int size; 70 int error; 71 struct iso_args args; 72 73 /* 74 * Get vnodes for swapdev and rootdev. 75 */ 76 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 77 panic("cd9660_mountroot: can't setup bdevvp's"); 78 79 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 80 bzero((char *)mp, (u_long)sizeof(struct mount)); 81 mp->mnt_op = &cd9660_vfsops; 82 mp->mnt_flag = MNT_RDONLY; 83 LIST_INIT(&mp->mnt_vnodelist); 84 args.flags = ISOFSMNT_ROOT; 85 if (error = iso_mountfs(rootvp, mp, p, &args)) { 86 free(mp, M_MOUNT); 87 return (error); 88 } 89 if (error = vfs_lock(mp)) { 90 (void)cd9660_unmount(mp, 0, p); 91 free(mp, M_MOUNT); 92 return (error); 93 } 94 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 95 mp->mnt_flag |= MNT_ROOTFS; 96 mp->mnt_vnodecovered = NULLVP; 97 imp = VFSTOISOFS(mp); 98 bzero(imp->im_fsmnt, sizeof(imp->im_fsmnt)); 99 imp->im_fsmnt[0] = '/'; 100 bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 101 MNAMELEN); 102 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 103 &size); 104 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 105 (void) cd9660_statfs(mp, &mp->mnt_stat, p); 106 vfs_unlock(mp); 107 return (0); 108 } 109 110 /* 111 * VFS Operations. 112 * 113 * mount system call 114 */ 115 cd9660_mount(mp, path, data, ndp, p) 116 register struct mount *mp; 117 char *path; 118 caddr_t data; 119 struct nameidata *ndp; 120 struct proc *p; 121 { 122 struct vnode *devvp; 123 struct iso_args args; 124 u_int size; 125 int error; 126 struct iso_mnt *imp; 127 128 if (error = copyin(data, (caddr_t)&args, sizeof (struct iso_args))) 129 return (error); 130 131 if ((mp->mnt_flag & MNT_RDONLY) == 0) 132 return (EROFS); 133 134 /* 135 * If updating, check whether changing from read-only to 136 * read/write; if there is no device name, that's all we do. 137 */ 138 if (mp->mnt_flag & MNT_UPDATE) { 139 imp = VFSTOISOFS(mp); 140 if (args.fspec == 0) 141 return (vfs_export(mp, &imp->im_export, &args.export)); 142 } 143 /* 144 * Not an update, or updating the name: look up the name 145 * and verify that it refers to a sensible block device. 146 */ 147 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 148 if (error = namei(ndp)) 149 return (error); 150 devvp = ndp->ni_vp; 151 152 if (devvp->v_type != VBLK) { 153 vrele(devvp); 154 return ENOTBLK; 155 } 156 if (major(devvp->v_rdev) >= nblkdev) { 157 vrele(devvp); 158 return ENXIO; 159 } 160 if ((mp->mnt_flag & MNT_UPDATE) == 0) 161 error = iso_mountfs(devvp, mp, p, &args); 162 else { 163 if (devvp != imp->im_devvp) 164 error = EINVAL; /* needs translation */ 165 else 166 vrele(devvp); 167 } 168 if (error) { 169 vrele(devvp); 170 return error; 171 } 172 imp = VFSTOISOFS(mp); 173 (void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size); 174 bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size); 175 bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 176 MNAMELEN); 177 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 178 &size); 179 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 180 (void) cd9660_statfs(mp, &mp->mnt_stat, p); 181 return 0; 182 } 183 184 /* 185 * Common code for mount and mountroot 186 */ 187 static iso_mountfs(devvp, mp, p, argp) 188 register struct vnode *devvp; 189 struct mount *mp; 190 struct proc *p; 191 struct iso_args *argp; 192 { 193 register struct iso_mnt *isomp = (struct iso_mnt *)0; 194 struct buf *bp = NULL; 195 dev_t dev = devvp->v_rdev; 196 caddr_t base, space; 197 int havepart = 0, blks; 198 int error = EINVAL, i, size; 199 int needclose = 0; 200 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 201 extern struct vnode *rootvp; 202 int j; 203 int iso_bsize; 204 int iso_blknum; 205 struct iso_volume_descriptor *vdp; 206 struct iso_primary_descriptor *pri; 207 struct iso_directory_record *rootp; 208 int logical_block_size; 209 210 if (!ronly) 211 return EROFS; 212 213 /* 214 * Disallow multiple mounts of the same device. 215 * Disallow mounting of a device that is currently in use 216 * (except for root, which might share swap device for miniroot). 217 * Flush out any old buffers remaining from a previous use. 218 */ 219 if (error = vfs_mountedon(devvp)) 220 return error; 221 if (vcount(devvp) > 1 && devvp != rootvp) 222 return EBUSY; 223 if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) 224 return (error); 225 226 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) 227 return error; 228 needclose = 1; 229 230 /* This is the "logical sector size". The standard says this 231 * should be 2048 or the physical sector size on the device, 232 * whichever is greater. For now, we'll just use a constant. 233 */ 234 iso_bsize = ISO_DEFAULT_BLOCK_SIZE; 235 236 for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) { 237 if (error = bread(devvp, iso_blknum * btodb(iso_bsize), 238 iso_bsize, NOCRED, &bp)) 239 goto out; 240 241 vdp = (struct iso_volume_descriptor *)bp->b_data; 242 if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) { 243 error = EINVAL; 244 goto out; 245 } 246 247 if (isonum_711 (vdp->type) == ISO_VD_END) { 248 error = EINVAL; 249 goto out; 250 } 251 252 if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) 253 break; 254 brelse(bp); 255 } 256 257 if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) { 258 error = EINVAL; 259 goto out; 260 } 261 262 pri = (struct iso_primary_descriptor *)vdp; 263 264 logical_block_size = isonum_723 (pri->logical_block_size); 265 266 if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE 267 || (logical_block_size & (logical_block_size - 1)) != 0) { 268 error = EINVAL; 269 goto out; 270 } 271 272 rootp = (struct iso_directory_record *)pri->root_directory_record; 273 274 isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK); 275 bzero((caddr_t)isomp, sizeof *isomp); 276 isomp->logical_block_size = logical_block_size; 277 isomp->volume_space_size = isonum_733 (pri->volume_space_size); 278 bcopy (rootp, isomp->root, sizeof isomp->root); 279 isomp->root_extent = isonum_733 (rootp->extent); 280 isomp->root_size = isonum_733 (rootp->size); 281 282 isomp->im_bmask = logical_block_size - 1; 283 isomp->im_bshift = 0; 284 while ((1 << isomp->im_bshift) < isomp->logical_block_size) 285 isomp->im_bshift++; 286 287 bp->b_flags |= B_AGE; 288 brelse(bp); 289 bp = NULL; 290 291 mp->mnt_data = (qaddr_t)isomp; 292 mp->mnt_stat.f_fsid.val[0] = (long)dev; 293 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 294 mp->mnt_maxsymlinklen = 0; 295 mp->mnt_flag |= MNT_LOCAL; 296 isomp->im_mountp = mp; 297 isomp->im_dev = dev; 298 isomp->im_devvp = devvp; 299 300 devvp->v_specflags |= SI_MOUNTEDON; 301 302 /* Check the Rock Ridge Extention support */ 303 if (!(argp->flags & ISOFSMNT_NORRIP)) { 304 if (error = bread(isomp->im_devvp, 305 (isomp->root_extent + isonum_711(rootp->ext_attr_length)) << 306 (isomp->im_bshift - DEV_BSHIFT), 307 isomp->logical_block_size, NOCRED, &bp)) 308 goto out; 309 310 rootp = (struct iso_directory_record *)bp->b_data; 311 312 if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) { 313 argp->flags |= ISOFSMNT_NORRIP; 314 } else { 315 argp->flags &= ~ISOFSMNT_GENS; 316 } 317 318 /* 319 * The contents are valid, 320 * but they will get reread as part of another vnode, so... 321 */ 322 bp->b_flags |= B_AGE; 323 brelse(bp); 324 bp = NULL; 325 } 326 isomp->im_flags = argp->flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS|ISOFSMNT_EXTATT); 327 switch (isomp->im_flags&(ISOFSMNT_NORRIP|ISOFSMNT_GENS)) { 328 default: 329 isomp->iso_ftype = ISO_FTYPE_DEFAULT; 330 break; 331 case ISOFSMNT_GENS|ISOFSMNT_NORRIP: 332 isomp->iso_ftype = ISO_FTYPE_9660; 333 break; 334 case 0: 335 isomp->iso_ftype = ISO_FTYPE_RRIP; 336 break; 337 } 338 339 return 0; 340 out: 341 if (bp) 342 brelse(bp); 343 if (needclose) 344 (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); 345 if (isomp) { 346 free((caddr_t)isomp, M_ISOFSMNT); 347 mp->mnt_data = (qaddr_t)0; 348 } 349 return error; 350 } 351 352 /* 353 * Make a filesystem operational. 354 * Nothing to do at the moment. 355 */ 356 /* ARGSUSED */ 357 cd9660_start(mp, flags, p) 358 struct mount *mp; 359 int flags; 360 struct proc *p; 361 { 362 return 0; 363 } 364 365 /* 366 * unmount system call 367 */ 368 int 369 cd9660_unmount(mp, mntflags, p) 370 struct mount *mp; 371 int mntflags; 372 struct proc *p; 373 { 374 register struct iso_mnt *isomp; 375 int i, error, ronly, flags = 0; 376 377 if (mntflags & MNT_FORCE) { 378 extern int doforce; 379 380 if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) 381 return (EINVAL); 382 flags |= FORCECLOSE; 383 } 384 #if 0 385 mntflushbuf(mp, 0); 386 if (mntinvalbuf(mp)) 387 return EBUSY; 388 #endif 389 if (error = vflush(mp, NULLVP, flags)) 390 return (error); 391 392 isomp = VFSTOISOFS(mp); 393 394 #ifdef ISODEVMAP 395 if (isomp->iso_ftype == ISO_FTYPE_RRIP) 396 iso_dunmap(isomp->im_dev); 397 #endif 398 399 isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON; 400 error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p); 401 vrele(isomp->im_devvp); 402 free((caddr_t)isomp, M_ISOFSMNT); 403 mp->mnt_data = (qaddr_t)0; 404 mp->mnt_flag &= ~MNT_LOCAL; 405 return (error); 406 } 407 408 /* 409 * Return root of a filesystem 410 */ 411 cd9660_root(mp, vpp) 412 struct mount *mp; 413 struct vnode **vpp; 414 { 415 struct iso_mnt *imp = VFSTOISOFS(mp); 416 struct iso_directory_record *dp = 417 (struct iso_directory_record *)imp->root; 418 ino_t ino = isodirino(dp, imp); 419 420 /* 421 * With RRIP we must use the `.' entry of the root directory. 422 * Simply tell vget, that it's a relocated directory. 423 */ 424 return (cd9660_vget_internal(mp, ino, vpp, 425 imp->iso_ftype == ISO_FTYPE_RRIP, dp)); 426 } 427 428 /* 429 * Do operations associated with quotas, not supported 430 */ 431 /* ARGSUSED */ 432 int 433 cd9660_quotactl(mp, cmd, uid, arg, p) 434 struct mount *mp; 435 int cmd; 436 uid_t uid; 437 caddr_t arg; 438 struct proc *p; 439 { 440 441 return (EOPNOTSUPP); 442 } 443 444 /* 445 * Get file system statistics. 446 */ 447 cd9660_statfs(mp, sbp, p) 448 struct mount *mp; 449 register struct statfs *sbp; 450 struct proc *p; 451 { 452 register struct iso_mnt *isomp; 453 register struct fs *fs; 454 455 isomp = VFSTOISOFS(mp); 456 457 #ifdef COMPAT_09 458 sbp->f_type = 5; 459 #else 460 sbp->f_type = 0; 461 #endif 462 sbp->f_bsize = isomp->logical_block_size; 463 sbp->f_iosize = sbp->f_bsize; /* XXX */ 464 sbp->f_blocks = isomp->volume_space_size; 465 sbp->f_bfree = 0; /* total free blocks */ 466 sbp->f_bavail = 0; /* blocks free for non superuser */ 467 sbp->f_files = 0; /* total files */ 468 sbp->f_ffree = 0; /* free file nodes */ 469 if (sbp != &mp->mnt_stat) { 470 bcopy((caddr_t)mp->mnt_stat.f_mntonname, 471 (caddr_t)&sbp->f_mntonname[0], MNAMELEN); 472 bcopy((caddr_t)mp->mnt_stat.f_mntfromname, 473 (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); 474 } 475 /* Use the first spare for flags: */ 476 sbp->f_spare[0] = isomp->im_flags; 477 return 0; 478 } 479 480 /* ARGSUSED */ 481 int 482 cd9660_sync(mp, waitfor, cred, p) 483 struct mount *mp; 484 int waitfor; 485 struct ucred *cred; 486 struct proc *p; 487 { 488 return (0); 489 } 490 491 /* 492 * File handle to vnode 493 * 494 * Have to be really careful about stale file handles: 495 * - check that the inode number is in range 496 * - call iget() to get the locked inode 497 * - check for an unallocated inode (i_mode == 0) 498 * - check that the generation number matches 499 */ 500 501 struct ifid { 502 ushort ifid_len; 503 ushort ifid_pad; 504 int ifid_ino; 505 long ifid_start; 506 }; 507 508 /* ARGSUSED */ 509 int 510 cd9660_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 511 register struct mount *mp; 512 struct fid *fhp; 513 struct mbuf *nam; 514 struct vnode **vpp; 515 int *exflagsp; 516 struct ucred **credanonp; 517 { 518 struct ifid *ifhp = (struct ifid *)fhp; 519 register struct iso_node *ip; 520 register struct netcred *np; 521 register struct iso_mnt *imp = VFSTOISOFS(mp); 522 struct vnode *nvp; 523 int error; 524 525 #ifdef ISOFS_DBG 526 printf("fhtovp: ino %d, start %ld\n", 527 ifhp->ifid_ino, ifhp->ifid_start); 528 #endif 529 530 /* 531 * Get the export permission structure for this <mp, client> tuple. 532 */ 533 np = vfs_export_lookup(mp, &imp->im_export, nam); 534 if (np == NULL) 535 return (EACCES); 536 537 if (error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) { 538 *vpp = NULLVP; 539 return (error); 540 } 541 ip = VTOI(nvp); 542 if (ip->inode.iso_mode == 0) { 543 vput(nvp); 544 *vpp = NULLVP; 545 return (ESTALE); 546 } 547 *vpp = nvp; 548 *exflagsp = np->netc_exflags; 549 *credanonp = &np->netc_anon; 550 return (0); 551 } 552 553 int 554 cd9660_vget(mp, ino, vpp) 555 struct mount *mp; 556 ino_t ino; 557 struct vnode **vpp; 558 { 559 560 /* 561 * XXXX 562 * It would be nice if we didn't always set the `relocated' flag 563 * and force the extra read, but I don't want to think about fixing 564 * that right now. 565 */ 566 return (cd9660_vget_internal(mp, ino, vpp, 567 #if 0 568 VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP, 569 #else 570 0, 571 #endif 572 (struct iso_directory_entry *)0)); 573 } 574 575 int 576 cd9660_vget_internal(mp, ino, vpp, relocated, isodir) 577 struct mount *mp; 578 ino_t ino; 579 struct vnode **vpp; 580 int relocated; 581 struct iso_directory_record *isodir; 582 { 583 register struct iso_mnt *imp; 584 struct iso_node *ip; 585 struct buf *bp; 586 struct vnode *vp, *nvp; 587 dev_t dev; 588 int error; 589 590 imp = VFSTOISOFS(mp); 591 dev = imp->im_dev; 592 if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP) 593 return (0); 594 595 /* Allocate a new vnode/iso_node. */ 596 if (error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) { 597 *vpp = NULLVP; 598 return (error); 599 } 600 MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE, 601 M_WAITOK); 602 bzero((caddr_t)ip, sizeof(struct iso_node)); 603 vp->v_data = ip; 604 ip->i_vnode = vp; 605 ip->i_dev = dev; 606 ip->i_number = ino; 607 608 /* 609 * Put it onto its hash chain and lock it so that other requests for 610 * this inode will block if they arrive while we are sleeping waiting 611 * for old data structures to be purged or for the contents of the 612 * disk portion of this inode to be read. 613 */ 614 cd9660_ihashins(ip); 615 616 if (isodir == 0) { 617 int lbn, off; 618 619 lbn = lblkno(imp, ino); 620 if (lbn >= imp->volume_space_size) { 621 vput(vp); 622 printf("fhtovp: lbn exceed volume space %d\n", lbn); 623 return (ESTALE); 624 } 625 626 off = blkoff(imp, ino); 627 if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) { 628 vput(vp); 629 printf("fhtovp: crosses block boundary %d\n", 630 off + ISO_DIRECTORY_RECORD_SIZE); 631 return (ESTALE); 632 } 633 634 error = bread(imp->im_devvp, 635 lbn << (imp->im_bshift - DEV_BSHIFT), 636 imp->logical_block_size, NOCRED, &bp); 637 if (error) { 638 vput(vp); 639 brelse(bp); 640 printf("fhtovp: bread error %d\n",error); 641 return (error); 642 } 643 isodir = (struct iso_directory_record *)(bp->b_data + off); 644 645 if (off + isonum_711(isodir->length) > 646 imp->logical_block_size) { 647 vput(vp); 648 if (bp != 0) 649 brelse(bp); 650 printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n", 651 off +isonum_711(isodir->length), off, 652 isonum_711(isodir->length)); 653 return (ESTALE); 654 } 655 656 #if 0 657 if (isonum_733(isodir->extent) + 658 isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) { 659 if (bp != 0) 660 brelse(bp); 661 printf("fhtovp: file start miss %d vs %d\n", 662 isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length), 663 ifhp->ifid_start); 664 return (ESTALE); 665 } 666 #endif 667 } else 668 bp = 0; 669 670 ip->i_mnt = imp; 671 ip->i_devvp = imp->im_devvp; 672 VREF(ip->i_devvp); 673 674 if (relocated) { 675 /* 676 * On relocated directories we must 677 * read the `.' entry out of a dir. 678 */ 679 ip->iso_start = ino >> imp->im_bshift; 680 if (bp != 0) 681 brelse(bp); 682 if (error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) { 683 vput(vp); 684 return (error); 685 } 686 isodir = (struct iso_directory_record *)bp->b_data; 687 } 688 689 ip->iso_extent = isonum_733(isodir->extent); 690 ip->i_size = isonum_733(isodir->size); 691 ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent; 692 693 /* 694 * Setup time stamp, attribute 695 */ 696 vp->v_type = VNON; 697 switch (imp->iso_ftype) { 698 default: /* ISO_FTYPE_9660 */ 699 { 700 struct buf *bp2; 701 int off; 702 if ((imp->im_flags & ISOFSMNT_EXTATT) 703 && (off = isonum_711(isodir->ext_attr_length))) 704 VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL, 705 &bp2); 706 else 707 bp2 = NULL; 708 cd9660_defattr(isodir, ip, bp2); 709 cd9660_deftstamp(isodir, ip, bp2); 710 if (bp2) 711 brelse(bp2); 712 break; 713 } 714 case ISO_FTYPE_RRIP: 715 cd9660_rrip_analyze(isodir, ip, imp); 716 break; 717 } 718 719 if (bp != 0) 720 brelse(bp); 721 722 /* 723 * Initialize the associated vnode 724 */ 725 switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) { 726 case VFIFO: 727 #ifdef FIFO 728 vp->v_op = cd9660_fifoop_p; 729 break; 730 #else 731 vput(vp); 732 return (EOPNOTSUPP); 733 #endif /* FIFO */ 734 case VCHR: 735 case VBLK: 736 /* 737 * if device, look at device number table for translation 738 */ 739 #ifdef ISODEVMAP 740 if (dp = iso_dmap(dev, ino, 0)) 741 ip->inode.iso_rdev = dp->d_dev; 742 #endif 743 vp->v_op = cd9660_specop_p; 744 if (nvp = checkalias(vp, ip->inode.iso_rdev, mp)) { 745 /* 746 * Discard unneeded vnode, but save its iso_node. 747 */ 748 cd9660_ihashrem(ip); 749 VOP_UNLOCK(vp); 750 nvp->v_data = vp->v_data; 751 vp->v_data = NULL; 752 vp->v_op = spec_vnodeop_p; 753 vrele(vp); 754 vgone(vp); 755 /* 756 * Reinitialize aliased inode. 757 */ 758 vp = nvp; 759 ip->i_vnode = vp; 760 cd9660_ihashins(ip); 761 } 762 break; 763 } 764 765 if (ip->iso_extent == imp->root_extent) 766 vp->v_flag |= VROOT; 767 768 /* 769 * XXX need generation number? 770 */ 771 772 *vpp = vp; 773 return (0); 774 } 775 776 /* 777 * Vnode pointer to File handle 778 */ 779 /* ARGSUSED */ 780 cd9660_vptofh(vp, fhp) 781 struct vnode *vp; 782 struct fid *fhp; 783 { 784 register struct iso_node *ip = VTOI(vp); 785 register struct ifid *ifhp; 786 register struct iso_mnt *mp = ip->i_mnt; 787 788 ifhp = (struct ifid *)fhp; 789 ifhp->ifid_len = sizeof(struct ifid); 790 791 ifhp->ifid_ino = ip->i_number; 792 ifhp->ifid_start = ip->iso_start; 793 794 #ifdef ISOFS_DBG 795 printf("vptofh: ino %d, start %ld\n", 796 ifhp->ifid_ino,ifhp->ifid_start); 797 #endif 798 return 0; 799 } 800