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