genfs_node_init(vp, &cd9660_genfsops);
cd9660_vget_internal(mp, ino, vpp, relocated, isodir)	struct mount *mp;	ino_t ino;	struct vnode **vpp;	int relocated;	struct iso_directory_record *isodir;{	register struct iso_mnt *imp;	struct iso_node *ip;	struct buf *bp;	struct vnode *vp, *nvp;	dev_t dev;	int error;retry:	imp = VFSTOISOFS(mp);	dev = imp->im_dev;	if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)		return (0);	/* Allocate a new vnode/iso_node. */	if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {		*vpp = NULLVP;		return (error);	}	MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,	    M_WAITOK);	bzero((caddr_t)ip, sizeof(struct iso_node));	lockinit(&ip->i_lock, PINOD, "isoinode", 0, 0);	vp->v_data = ip;	ip->i_vnode = vp;	ip->i_dev = dev;	ip->i_number = ino;	/*	 * Put it onto its hash chain and lock it so that other requests for	 * this inode will block if they arrive while we are sleeping waiting	 * for old data structures to be purged or for the contents of the	 * disk portion of this inode to be read.	 */	error = cd9660_ihashins(ip);	if (error) {		vrele(vp);		if (error == EEXIST)			goto retry;		return (error);	}	if (isodir == 0) {		int lbn, off;		lbn = lblkno(imp, ino);		if (lbn >= imp->volume_space_size) {			vput(vp);			printf("fhtovp: lbn exceed volume space %d\n", lbn);			return (ESTALE);		}			off = blkoff(imp, ino);		if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size)		    {			vput(vp);			printf("fhtovp: crosses block boundary %d\n",			    off + ISO_DIRECTORY_RECORD_SIZE);			return (ESTALE);		}			error = bread(imp->im_devvp,			      lbn << (imp->im_bshift - DEV_BSHIFT),			      imp->logical_block_size, NOCRED, &bp);		if (error) {			vput(vp);			brelse(bp);			printf("fhtovp: bread error %d\n",error);			return (error);		}		isodir = (struct iso_directory_record *)(bp->b_data + off);		if (off + isonum_711(isodir->length) >		    imp->logical_block_size) {			vput(vp);			if (bp != 0)				brelse(bp);			printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",			    off +isonum_711(isodir->length), off,			    isonum_711(isodir->length));			return (ESTALE);		}	#if 0		if (isonum_733(isodir->extent) +		    isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {			if (bp != 0)				brelse(bp);			printf("fhtovp: file start miss %d vs %d\n",			    isonum_733(isodir->extent) +			    isonum_711(isodir->ext_attr_length),			    ifhp->ifid_start);			return (ESTALE);		}#endif	} else		bp = 0;	ip->i_mnt = imp;	ip->i_devvp = imp->im_devvp;	VREF(ip->i_devvp);	if (relocated) {		/*		 * On relocated directories we must		 * read the `.' entry out of a dir.		 */		ip->iso_start = ino >> imp->im_bshift;		if (bp != 0)			brelse(bp);		if ((error = cd9660_bufatoff(ip, (off_t)0, NULL, &bp)) != 0) {			vput(vp);			return (error);		}		isodir = (struct iso_directory_record *)bp->b_data;	}	ip->iso_extent = isonum_733(isodir->extent);	ip->i_size = isonum_733(isodir->size);	ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;		/*	 * Setup time stamp, attribute	 */	vp->v_type = VNON;	switch (imp->iso_ftype) {	default:	/* ISO_FTYPE_9660 */	    {		struct buf *bp2;		int off;		if ((imp->im_flags & ISOFSMNT_EXTATT) && 		    (off = isonum_711(isodir->ext_attr_length)))			cd9660_bufatoff(ip, (off_t)-(off << imp->im_bshift),			    NULL, &bp2);		else			bp2 = NULL;		cd9660_defattr(isodir, ip, bp2);		cd9660_deftstamp(isodir, ip, bp2);		if (bp2)			brelse(bp2);		break;	    }	case ISO_FTYPE_RRIP:		cd9660_rrip_analyze(isodir, ip, imp);		break;	}	if (bp != 0)		brelse(bp);	/*	 * Initialize the associated vnode	 */	switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {	case VFIFO:#ifdef	FIFO		vp->v_op = cd9660_fifoop_p;		break;#else		vput(vp);		return (EOPNOTSUPP);#endif	/* FIFO */	case VCHR:	case VBLK:		/*		 * if device, look at device number table for translation		 */#ifdef	ISODEVMAP		if (dp = iso_dmap(dev, ino, 0))			ip->inode.iso_rdev = dp->d_dev;#endif		vp->v_op = cd9660_specop_p;		if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {			/*			 * Discard unneeded vnode, but save its iso_node.			 * Note that the lock is carried over in the iso_node			 */			nvp->v_data = vp->v_data;			vp->v_data = NULL;			vp->v_op = spec_vnodeop_p;			vrele(vp);			vgone(vp);			/*			 * Reinitialize aliased inode.			 */			vp = nvp;			ip->i_vnode = vp;		}		break;	case VLNK:	case VNON:	case VSOCK:	case VDIR:	case VBAD:		break;	case VREG:		uvm_vnp_setsize(vp, ip->i_size);		break;	}		if (ip->iso_extent == imp->root_extent)		vp->v_flag |= VROOT;	/*	 * XXX need generation number?	 */	genfs_node_init(vp, &cd9660_genfsops);	*vpp = vp;	return (0);}