Annotation of src/sys/fs/cd9660/cd9660_vfsops.c, Revision 1.6
1.6 ! darrenr 1: /* $NetBSD: cd9660_vfsops.c,v 1.5 2003/04/16 21:44:19 christos Exp $ */
1.1 jdolecek 2:
3: /*-
4: * Copyright (c) 1994
5: * The Regents of the University of California. All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley
8: * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
9: * Support code is derived from software contributed to Berkeley
10: * by Atsushi Murai (amurai@spec.co.jp).
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the University of
23: * California, Berkeley and its contributors.
24: * 4. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
40: * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
41: */
42:
43: #include <sys/cdefs.h>
1.6 ! darrenr 44: __KERNEL_RCSID(0, "$NetBSD: cd9660_vfsops.c,v 1.5 2003/04/16 21:44:19 christos Exp $");
1.1 jdolecek 45:
46: #if defined(_KERNEL_OPT)
47: #include "opt_compat_netbsd.h"
48: #endif
49:
50: #include <sys/param.h>
51: #include <sys/systm.h>
52: #include <sys/namei.h>
53: #include <sys/proc.h>
54: #include <sys/kernel.h>
55: #include <sys/vnode.h>
56: #include <miscfs/specfs/specdev.h>
57: #include <sys/mount.h>
58: #include <sys/buf.h>
59: #include <sys/file.h>
60: #include <sys/disklabel.h>
61: #include <sys/device.h>
62: #include <sys/ioctl.h>
63: #include <sys/cdio.h>
64: #include <sys/errno.h>
65: #include <sys/malloc.h>
66: #include <sys/pool.h>
67: #include <sys/stat.h>
68: #include <sys/conf.h>
69:
70: #include <fs/cd9660/iso.h>
71: #include <fs/cd9660/cd9660_extern.h>
72: #include <fs/cd9660/iso_rrip.h>
73: #include <fs/cd9660/cd9660_node.h>
74: #include <fs/cd9660/cd9660_mount.h>
1.2 thorpej 75:
76: MALLOC_DEFINE(M_ISOFSMNT, "ISOFS mount", "ISOFS mount structure");
1.1 jdolecek 77:
78: extern const struct vnodeopv_desc cd9660_vnodeop_opv_desc;
79: extern const struct vnodeopv_desc cd9660_specop_opv_desc;
80: extern const struct vnodeopv_desc cd9660_fifoop_opv_desc;
81:
82: const struct vnodeopv_desc * const cd9660_vnodeopv_descs[] = {
83: &cd9660_vnodeop_opv_desc,
84: &cd9660_specop_opv_desc,
85: &cd9660_fifoop_opv_desc,
86: NULL,
87: };
88:
89: struct vfsops cd9660_vfsops = {
90: MOUNT_CD9660,
91: cd9660_mount,
92: cd9660_start,
93: cd9660_unmount,
94: cd9660_root,
95: cd9660_quotactl,
96: cd9660_statfs,
97: cd9660_sync,
98: cd9660_vget,
99: cd9660_fhtovp,
100: cd9660_vptofh,
101: cd9660_init,
102: cd9660_reinit,
103: cd9660_done,
104: cd9660_sysctl,
105: cd9660_mountroot,
106: cd9660_check_export,
107: cd9660_vnodeopv_descs,
108: };
109:
110: struct genfs_ops cd9660_genfsops = {
111: genfs_size,
112: };
113:
114: /*
115: * Called by vfs_mountroot when iso is going to be mounted as root.
116: *
117: * Name is updated by mount(8) after booting.
118: */
119: #define ROOTNAME "root_device"
120:
121: static int iso_makemp __P((struct iso_mnt *isomp, struct buf *bp, int *ea_len));
122: static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
1.6 ! darrenr 123: struct lwp *l, struct iso_args *argp));
1.1 jdolecek 124:
125: int
126: cd9660_mountroot()
127: {
128: struct mount *mp;
1.6 ! darrenr 129: struct lwp *l = curlwp; /* XXX */
1.1 jdolecek 130: int error;
131: struct iso_args args;
132:
133: if (root_device->dv_class != DV_DISK)
134: return (ENODEV);
135:
136: /*
137: * Get vnodes for swapdev and rootdev.
138: */
139: if (bdevvp(rootdev, &rootvp))
140: panic("cd9660_mountroot: can't setup rootvp");
141:
142: if ((error = vfs_rootmountalloc(MOUNT_CD9660, "root_device", &mp))
143: != 0) {
144: vrele(rootvp);
145: return (error);
146: }
147:
148: args.flags = ISOFSMNT_ROOT;
1.6 ! darrenr 149: if ((error = iso_mountfs(rootvp, mp, l, &args)) != 0) {
1.1 jdolecek 150: mp->mnt_op->vfs_refcount--;
151: vfs_unbusy(mp);
152: free(mp, M_MOUNT);
153: vrele(rootvp);
154: return (error);
155: }
156: simple_lock(&mountlist_slock);
157: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
158: simple_unlock(&mountlist_slock);
1.6 ! darrenr 159: (void)cd9660_statfs(mp, &mp->mnt_stat, l);
1.1 jdolecek 160: vfs_unbusy(mp);
161: inittodr(0);
162: return (0);
163: }
164:
165: /*
166: * VFS Operations.
167: *
168: * mount system call
169: */
170: int
1.6 ! darrenr 171: cd9660_mount(mp, path, data, ndp, l)
1.1 jdolecek 172: struct mount *mp;
173: const char *path;
174: void *data;
175: struct nameidata *ndp;
1.6 ! darrenr 176: struct lwp *l;
1.1 jdolecek 177: {
178: struct vnode *devvp;
179: struct iso_args args;
1.6 ! darrenr 180: struct proc *p;
1.1 jdolecek 181: int error;
182: struct iso_mnt *imp = NULL;
1.6 ! darrenr 183:
! 184: p = l->l_proc;
1.1 jdolecek 185: if (mp->mnt_flag & MNT_GETARGS) {
186: imp = VFSTOISOFS(mp);
187: if (imp == NULL)
188: return EIO;
189: args.fspec = NULL;
190: args.flags = imp->im_flags;
191: vfs_showexport(mp, &args.export, &imp->im_export);
192: return copyout(&args, data, sizeof(args));
193: }
1.3 dsl 194: error = copyin(data, &args, sizeof (struct iso_args));
1.1 jdolecek 195: if (error)
196: return (error);
197:
198: if ((mp->mnt_flag & MNT_RDONLY) == 0)
199: return (EROFS);
200:
201: /*
202: * If updating, check whether changing from read-only to
203: * read/write; if there is no device name, that's all we do.
204: */
205: if (mp->mnt_flag & MNT_UPDATE) {
206: imp = VFSTOISOFS(mp);
207: if (args.fspec == 0)
208: return (vfs_export(mp, &imp->im_export, &args.export));
209: }
210: /*
211: * Not an update, or updating the name: look up the name
212: * and verify that it refers to a sensible block device.
213: */
1.6 ! darrenr 214: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, l);
1.1 jdolecek 215: if ((error = namei(ndp)) != 0)
216: return (error);
217: devvp = ndp->ni_vp;
218:
219: if (devvp->v_type != VBLK) {
220: vrele(devvp);
221: return ENOTBLK;
222: }
223: if (bdevsw_lookup(devvp->v_rdev) == NULL) {
224: vrele(devvp);
225: return ENXIO;
226: }
227: /*
228: * If mount by non-root, then verify that user has necessary
229: * permissions on the device.
230: */
231: if (p->p_ucred->cr_uid != 0) {
232: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.6 ! darrenr 233: error = VOP_ACCESS(devvp, VREAD, p->p_ucred, l);
1.1 jdolecek 234: VOP_UNLOCK(devvp, 0);
235: if (error) {
236: vrele(devvp);
237: return (error);
238: }
239: }
240: if ((mp->mnt_flag & MNT_UPDATE) == 0)
1.6 ! darrenr 241: error = iso_mountfs(devvp, mp, l, &args);
1.1 jdolecek 242: else {
243: if (devvp != imp->im_devvp)
244: error = EINVAL; /* needs translation */
245: else
246: vrele(devvp);
247: }
248: if (error) {
249: vrele(devvp);
250: return error;
251: }
252: imp = VFSTOISOFS(mp);
1.5 christos 253: return set_statfs_info(path, UIO_USERSPACE, args.fspec, UIO_USERSPACE,
1.6 ! darrenr 254: mp, l);
1.1 jdolecek 255: }
256:
257: /*
258: * Make a mount point from a volume descriptor
259: */
260: static int
261: iso_makemp(isomp, bp, ea_len)
262: struct iso_mnt *isomp;
263: struct buf *bp;
264: int *ea_len;
265: {
266: struct iso_primary_descriptor *pri;
267: int logical_block_size;
268: struct iso_directory_record *rootp;
269:
270: pri = (struct iso_primary_descriptor *)bp->b_data;
271:
272: logical_block_size = isonum_723 (pri->logical_block_size);
273:
274: if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
275: || (logical_block_size & (logical_block_size - 1)) != 0)
276: return -1;
277:
278: rootp = (struct iso_directory_record *)pri->root_directory_record;
279:
280: isomp->logical_block_size = logical_block_size;
281: isomp->volume_space_size = isonum_733 (pri->volume_space_size);
282: memcpy(isomp->root, rootp, sizeof(isomp->root));
283: isomp->root_extent = isonum_733 (rootp->extent);
284: isomp->root_size = isonum_733 (rootp->size);
285: isomp->im_joliet_level = 0;
286:
287: isomp->im_bmask = logical_block_size - 1;
288: isomp->im_bshift = 0;
289: while ((1 << isomp->im_bshift) < isomp->logical_block_size)
290: isomp->im_bshift++;
291:
292: if (ea_len != NULL)
293: *ea_len = isonum_711(rootp->ext_attr_length);
294:
295: return 0;
296: }
297:
298: /*
299: * Common code for mount and mountroot
300: */
301: static int
1.6 ! darrenr 302: iso_mountfs(devvp, mp, l, argp)
1.1 jdolecek 303: struct vnode *devvp;
304: struct mount *mp;
1.6 ! darrenr 305: struct lwp *l;
1.1 jdolecek 306: struct iso_args *argp;
307: {
308: struct iso_mnt *isomp = (struct iso_mnt *)0;
309: struct buf *bp = NULL, *pribp = NULL, *supbp = NULL;
310: dev_t dev = devvp->v_rdev;
311: int error = EINVAL;
312: int needclose = 0;
313: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
314: int iso_bsize;
315: int iso_blknum;
316: int joliet_level;
317: struct iso_volume_descriptor *vdp;
318: struct iso_supplementary_descriptor *sup;
319: int sess = 0;
320: int ext_attr_length;
321: struct disklabel label;
322:
323: if (!ronly)
324: return EROFS;
325:
326: /*
327: * Disallow multiple mounts of the same device.
328: * Disallow mounting of a device that is currently in use
329: * (except for root, which might share swap device for miniroot).
330: * Flush out any old buffers remaining from a previous use.
331: */
332: if ((error = vfs_mountedon(devvp)) != 0)
333: return error;
334: if (vcount(devvp) > 1 && devvp != rootvp)
335: return EBUSY;
1.6 ! darrenr 336: if ((error = vinvalbuf(devvp, V_SAVE, l->l_proc->p_ucred, l, 0, 0)) != 0)
1.1 jdolecek 337: return (error);
338:
1.6 ! darrenr 339: error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, l);
1.1 jdolecek 340: if (error)
341: return error;
342: needclose = 1;
343:
344: /* This is the "logical sector size". The standard says this
345: * should be 2048 or the physical sector size on the device,
346: * whichever is greater. For now, we'll just use a constant.
347: */
348: iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
349:
1.6 ! darrenr 350: error = VOP_IOCTL(devvp, DIOCGDINFO, &label, FREAD, FSCRED, l);
1.1 jdolecek 351: if (!error &&
352: label.d_partitions[DISKPART(dev)].p_fstype == FS_ISO9660) {
353: /* XXX more sanity checks? */
354: sess = label.d_partitions[DISKPART(dev)].p_cdsession;
355: } else {
356: /* fallback to old method */
1.6 ! darrenr 357: error = VOP_IOCTL(devvp, CDIOREADMSADDR, &sess, 0, FSCRED, l);
1.1 jdolecek 358: if (error)
359: sess = 0; /* never mind */
360: }
1.4 christos 361: #ifdef ISO_DEBUG
1.1 jdolecek 362: printf("isofs: session offset (part %d) %d\n", DISKPART(dev), sess);
363: #endif
364:
365: for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
366: if ((error = bread(devvp, (iso_blknum+sess) * btodb(iso_bsize),
367: iso_bsize, NOCRED, &bp)) != 0)
368: goto out;
369:
370: vdp = (struct iso_volume_descriptor *)bp->b_data;
371: if (memcmp(vdp->id, ISO_STANDARD_ID, sizeof(vdp->id)) != 0) {
372: error = EINVAL;
373: goto out;
374: }
375:
376: switch (isonum_711(vdp->type)) {
377: case ISO_VD_PRIMARY:
378: if (pribp == NULL) {
379: pribp = bp;
380: bp = NULL;
381: }
382: break;
383:
384: case ISO_VD_SUPPLEMENTARY:
385: if (supbp == NULL) {
386: supbp = bp;
387: bp = NULL;
388: }
389: break;
390:
391: default:
392: break;
393: }
394:
395: if (isonum_711 (vdp->type) == ISO_VD_END) {
396: brelse(bp);
397: bp = NULL;
398: break;
399: }
400:
401: if (bp != NULL) {
402: brelse(bp);
403: bp = NULL;
404: }
405: }
406:
407: if (pribp == NULL) {
408: error = EINVAL;
409: goto out;
410: }
411:
412: isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
1.3 dsl 413: memset(isomp, 0, sizeof *isomp);
1.1 jdolecek 414: if (iso_makemp(isomp, pribp, &ext_attr_length) == -1) {
415: error = EINVAL;
416: goto out;
417: }
418:
419: isomp->volume_space_size += sess;
420:
421: pribp->b_flags |= B_AGE;
422: brelse(pribp);
423: pribp = NULL;
424:
425: mp->mnt_data = isomp;
426: mp->mnt_stat.f_fsid.val[0] = (long)dev;
427: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_CD9660);
428: mp->mnt_maxsymlinklen = 0;
429: mp->mnt_flag |= MNT_LOCAL;
430: mp->mnt_dev_bshift = iso_bsize;
431: mp->mnt_fs_bshift = isomp->im_bshift;
432: isomp->im_mountp = mp;
433: isomp->im_dev = dev;
434: isomp->im_devvp = devvp;
435:
436: devvp->v_specmountpoint = mp;
437:
438: /* Check the Rock Ridge Extension support */
439: if (!(argp->flags & ISOFSMNT_NORRIP)) {
440: struct iso_directory_record *rootp;
441:
442: if ((error = bread(isomp->im_devvp,
443: (isomp->root_extent + ext_attr_length) <<
444: (isomp->im_bshift - DEV_BSHIFT),
445: isomp->logical_block_size, NOCRED,
446: &bp)) != 0)
447: goto out;
448:
449: rootp = (struct iso_directory_record *)bp->b_data;
450:
451: if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
452: argp->flags |= ISOFSMNT_NORRIP;
453: } else {
454: argp->flags &= ~ISOFSMNT_GENS;
455: }
456:
457: /*
458: * The contents are valid,
459: * but they will get reread as part of another vnode, so...
460: */
461: bp->b_flags |= B_AGE;
462: brelse(bp);
463: bp = NULL;
464: }
465: isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
466: ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | ISOFSMNT_RRCASEINS);
467:
468: if (isomp->im_flags & ISOFSMNT_GENS)
469: isomp->iso_ftype = ISO_FTYPE_9660;
470: else if (isomp->im_flags & ISOFSMNT_NORRIP) {
471: isomp->iso_ftype = ISO_FTYPE_DEFAULT;
472: if (argp->flags & ISOFSMNT_NOCASETRANS)
473: isomp->im_flags |= ISOFSMNT_NOCASETRANS;
474: } else
475: isomp->iso_ftype = ISO_FTYPE_RRIP;
476:
477: /* Check the Joliet Extension support */
478: if ((argp->flags & ISOFSMNT_NORRIP) != 0 &&
479: (argp->flags & ISOFSMNT_NOJOLIET) == 0 &&
480: supbp != NULL) {
481: joliet_level = 0;
482: sup = (struct iso_supplementary_descriptor *)supbp->b_data;
483:
484: if ((isonum_711(sup->flags) & 1) == 0) {
485: if (memcmp(sup->escape, "%/@", 3) == 0)
486: joliet_level = 1;
487: if (memcmp(sup->escape, "%/C", 3) == 0)
488: joliet_level = 2;
489: if (memcmp(sup->escape, "%/E", 3) == 0)
490: joliet_level = 3;
491: }
492: if (joliet_level != 0) {
493: if (iso_makemp(isomp, supbp, NULL) == -1) {
494: error = EINVAL;
495: goto out;
496: }
497: isomp->im_joliet_level = joliet_level;
498: }
499: }
500:
501: if (supbp != NULL) {
502: brelse(supbp);
503: supbp = NULL;
504: }
505:
506: return 0;
507: out:
508: if (bp)
509: brelse(bp);
510: if (pribp)
511: brelse(pribp);
512: if (supbp)
513: brelse(supbp);
514: if (needclose) {
515: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.6 ! darrenr 516: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, l);
1.1 jdolecek 517: VOP_UNLOCK(devvp, 0);
518: }
519: if (isomp) {
1.3 dsl 520: free(isomp, M_ISOFSMNT);
1.1 jdolecek 521: mp->mnt_data = NULL;
522: }
523: return error;
524: }
525:
526: /*
527: * Make a filesystem operational.
528: * Nothing to do at the moment.
529: */
530: /* ARGSUSED */
531: int
1.6 ! darrenr 532: cd9660_start(mp, flags, l)
1.1 jdolecek 533: struct mount *mp;
534: int flags;
1.6 ! darrenr 535: struct lwp *l;
1.1 jdolecek 536: {
537: return 0;
538: }
539:
540: /*
541: * unmount system call
542: */
543: int
1.6 ! darrenr 544: cd9660_unmount(mp, mntflags, l)
1.1 jdolecek 545: struct mount *mp;
546: int mntflags;
1.6 ! darrenr 547: struct lwp *l;
1.1 jdolecek 548: {
549: struct iso_mnt *isomp;
550: int error, flags = 0;
551:
552: if (mntflags & MNT_FORCE)
553: flags |= FORCECLOSE;
554: #if 0
555: mntflushbuf(mp, 0);
556: if (mntinvalbuf(mp))
557: return EBUSY;
558: #endif
559: if ((error = vflush(mp, NULLVP, flags)) != 0)
560: return (error);
561:
562: isomp = VFSTOISOFS(mp);
563:
564: #ifdef ISODEVMAP
565: if (isomp->iso_ftype == ISO_FTYPE_RRIP)
566: iso_dunmap(isomp->im_dev);
567: #endif
568:
569: if (isomp->im_devvp->v_type != VBAD)
570: isomp->im_devvp->v_specmountpoint = NULL;
571:
572: vn_lock(isomp->im_devvp, LK_EXCLUSIVE | LK_RETRY);
1.6 ! darrenr 573: error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, l);
1.1 jdolecek 574: vput(isomp->im_devvp);
1.3 dsl 575: free(isomp, M_ISOFSMNT);
1.1 jdolecek 576: mp->mnt_data = NULL;
577: mp->mnt_flag &= ~MNT_LOCAL;
578: return (error);
579: }
580:
581: /*
582: * Return root of a filesystem
583: */
584: int
1.6 ! darrenr 585: cd9660_root(mp, vpp, l)
1.1 jdolecek 586: struct mount *mp;
587: struct vnode **vpp;
1.6 ! darrenr 588: struct lwp *l;
1.1 jdolecek 589: {
590: struct iso_mnt *imp = VFSTOISOFS(mp);
591: struct iso_directory_record *dp =
592: (struct iso_directory_record *)imp->root;
593: ino_t ino = isodirino(dp, imp);
594:
595: /*
596: * With RRIP we must use the `.' entry of the root directory.
597: * Simply tell vget, that it's a relocated directory.
598: */
599: return (cd9660_vget_internal(mp, ino, vpp,
1.6 ! darrenr 600: imp->iso_ftype == ISO_FTYPE_RRIP, dp, l));
1.1 jdolecek 601: }
602:
603: /*
604: * Do operations associated with quotas, not supported
605: */
606: /* ARGSUSED */
607: int
1.6 ! darrenr 608: cd9660_quotactl(mp, cmd, uid, arg, l)
1.1 jdolecek 609: struct mount *mp;
610: int cmd;
611: uid_t uid;
612: caddr_t arg;
1.6 ! darrenr 613: struct lwp *l;
1.1 jdolecek 614: {
615:
616: return (EOPNOTSUPP);
617: }
618:
619: /*
620: * Get file system statistics.
621: */
622: int
1.6 ! darrenr 623: cd9660_statfs(mp, sbp, l)
1.1 jdolecek 624: struct mount *mp;
625: struct statfs *sbp;
1.6 ! darrenr 626: struct lwp *l;
1.1 jdolecek 627: {
628: struct iso_mnt *isomp;
629:
630: isomp = VFSTOISOFS(mp);
631:
632: #ifdef COMPAT_09
633: sbp->f_type = 5;
634: #else
635: sbp->f_type = 0;
636: #endif
637: sbp->f_bsize = isomp->logical_block_size;
638: sbp->f_iosize = sbp->f_bsize; /* XXX */
639: sbp->f_blocks = isomp->volume_space_size;
640: sbp->f_bfree = 0; /* total free blocks */
641: sbp->f_bavail = 0; /* blocks free for non superuser */
642: sbp->f_files = 0; /* total files */
643: sbp->f_ffree = 0; /* free file nodes */
1.5 christos 644: copy_statfs_info(sbp, mp);
1.1 jdolecek 645: /* Use the first spare for flags: */
646: sbp->f_spare[0] = isomp->im_flags;
647: return 0;
648: }
649:
650: /* ARGSUSED */
651: int
1.6 ! darrenr 652: cd9660_sync(mp, waitfor, cred, l)
1.1 jdolecek 653: struct mount *mp;
654: int waitfor;
655: struct ucred *cred;
1.6 ! darrenr 656: struct lwp *l;
1.1 jdolecek 657: {
658: return (0);
659: }
660:
661: /*
662: * File handle to vnode
663: *
664: * Have to be really careful about stale file handles:
665: * - check that the inode number is in range
666: * - call iget() to get the locked inode
667: * - check for an unallocated inode (i_mode == 0)
668: * - check that the generation number matches
669: */
670:
671: struct ifid {
672: ushort ifid_len;
673: ushort ifid_pad;
674: int ifid_ino;
675: long ifid_start;
676: };
677:
678: /* ARGSUSED */
679: int
1.6 ! darrenr 680: cd9660_fhtovp(mp, fhp, vpp, l)
1.1 jdolecek 681: struct mount *mp;
682: struct fid *fhp;
683: struct vnode **vpp;
1.6 ! darrenr 684: struct lwp *l;
1.1 jdolecek 685: {
686: struct ifid *ifhp = (struct ifid *)fhp;
687: struct iso_node *ip;
688: struct vnode *nvp;
689: int error;
690:
691: #ifdef ISOFS_DBG
692: printf("fhtovp: ino %d, start %ld\n",
693: ifhp->ifid_ino, ifhp->ifid_start);
694: #endif
695:
1.6 ! darrenr 696: if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp, l)) != 0) {
1.1 jdolecek 697: *vpp = NULLVP;
698: return (error);
699: }
700: ip = VTOI(nvp);
701: if (ip->inode.iso_mode == 0) {
702: vput(nvp);
703: *vpp = NULLVP;
704: return (ESTALE);
705: }
706: *vpp = nvp;
707: return (0);
708: }
709:
710: /* ARGSUSED */
711: int
712: cd9660_check_export(mp, nam, exflagsp, credanonp)
713: struct mount *mp;
714: struct mbuf *nam;
715: int *exflagsp;
716: struct ucred **credanonp;
717: {
718: struct netcred *np;
719: struct iso_mnt *imp = VFSTOISOFS(mp);
720:
721: #ifdef ISOFS_DBG
722: printf("check_export: ino %d, start %ld\n",
723: ifhp->ifid_ino, ifhp->ifid_start);
724: #endif
725:
726: /*
727: * Get the export permission structure for this <mp, client> tuple.
728: */
729: np = vfs_export_lookup(mp, &imp->im_export, nam);
730: if (np == NULL)
731: return (EACCES);
732:
733: *exflagsp = np->netc_exflags;
734: *credanonp = &np->netc_anon;
735: return (0);
736: }
737:
738: int
1.6 ! darrenr 739: cd9660_vget(mp, ino, vpp, l)
1.1 jdolecek 740: struct mount *mp;
741: ino_t ino;
742: struct vnode **vpp;
1.6 ! darrenr 743: struct lwp *l;
1.1 jdolecek 744: {
745:
746: /*
747: * XXXX
748: * It would be nice if we didn't always set the `relocated' flag
749: * and force the extra read, but I don't want to think about fixing
750: * that right now.
751: */
752: return (cd9660_vget_internal(mp, ino, vpp,
753: #if 0
754: VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
755: #else
756: 0,
757: #endif
1.6 ! darrenr 758: NULL, l));
1.1 jdolecek 759: }
760:
761: int
1.6 ! darrenr 762: cd9660_vget_internal(mp, ino, vpp, relocated, isodir, l)
1.1 jdolecek 763: struct mount *mp;
764: ino_t ino;
765: struct vnode **vpp;
766: int relocated;
767: struct iso_directory_record *isodir;
1.6 ! darrenr 768: struct lwp *l;
1.1 jdolecek 769: {
770: struct iso_mnt *imp;
771: struct iso_node *ip;
772: #ifdef ISODEVMAP
773: struct iso_dnode *dp;
774: #endif
775: struct buf *bp;
776: struct vnode *vp, *nvp;
777: dev_t dev;
778: int error;
779:
780: imp = VFSTOISOFS(mp);
781: dev = imp->im_dev;
1.6 ! darrenr 782: if ((*vpp = cd9660_ihashget(dev, ino, l)) != NULLVP)
1.1 jdolecek 783: return (0);
784:
785: /* Allocate a new vnode/iso_node. */
786: if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {
787: *vpp = NULLVP;
788: return (error);
789: }
790: ip = pool_get(&cd9660_node_pool, PR_WAITOK);
1.3 dsl 791: memset(ip, 0, sizeof(struct iso_node));
1.1 jdolecek 792: vp->v_data = ip;
793: ip->i_vnode = vp;
794: ip->i_dev = dev;
795: ip->i_number = ino;
796:
797: /*
798: * Put it onto its hash chain and lock it so that other requests for
799: * this inode will block if they arrive while we are sleeping waiting
800: * for old data structures to be purged or for the contents of the
801: * disk portion of this inode to be read.
802: */
803: cd9660_ihashins(ip);
804:
805: if (isodir == 0) {
806: int lbn, off;
807:
808: lbn = lblkno(imp, ino);
809: if (lbn >= imp->volume_space_size) {
810: vput(vp);
811: printf("fhtovp: lbn exceed volume space %d\n", lbn);
812: return (ESTALE);
813: }
814:
815: off = blkoff(imp, ino);
816: if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) {
817: vput(vp);
818: printf("fhtovp: crosses block boundary %d\n",
819: off + ISO_DIRECTORY_RECORD_SIZE);
820: return (ESTALE);
821: }
822:
823: error = bread(imp->im_devvp,
824: lbn << (imp->im_bshift - DEV_BSHIFT),
825: imp->logical_block_size, NOCRED, &bp);
826: if (error) {
827: vput(vp);
828: brelse(bp);
829: printf("fhtovp: bread error %d\n",error);
830: return (error);
831: }
832: isodir = (struct iso_directory_record *)(bp->b_data + off);
833:
834: if (off + isonum_711(isodir->length) >
835: imp->logical_block_size) {
836: vput(vp);
837: if (bp != 0)
838: brelse(bp);
839: printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
840: off +isonum_711(isodir->length), off,
841: isonum_711(isodir->length));
842: return (ESTALE);
843: }
844:
845: #if 0
846: if (isonum_733(isodir->extent) +
847: isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
848: if (bp != 0)
849: brelse(bp);
850: printf("fhtovp: file start miss %d vs %d\n",
851: isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
852: ifhp->ifid_start);
853: return (ESTALE);
854: }
855: #endif
856: } else
857: bp = 0;
858:
859: ip->i_mnt = imp;
860: ip->i_devvp = imp->im_devvp;
861: VREF(ip->i_devvp);
862:
863: if (relocated) {
864: /*
865: * On relocated directories we must
866: * read the `.' entry out of a dir.
867: */
868: ip->iso_start = ino >> imp->im_bshift;
869: if (bp != 0)
870: brelse(bp);
871: if ((error = VOP_BLKATOFF(vp, (off_t)0, NULL, &bp)) != 0) {
872: vput(vp);
873: return (error);
874: }
875: isodir = (struct iso_directory_record *)bp->b_data;
876: }
877:
878: ip->iso_extent = isonum_733(isodir->extent);
879: ip->i_size = isonum_733(isodir->size);
880: ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
881:
882: /*
883: * Setup time stamp, attribute
884: */
885: vp->v_type = VNON;
886: switch (imp->iso_ftype) {
887: default: /* ISO_FTYPE_9660 */
888: {
889: struct buf *bp2;
890: int off;
891: if ((imp->im_flags & ISOFSMNT_EXTATT)
892: && (off = isonum_711(isodir->ext_attr_length)))
893: VOP_BLKATOFF(vp, (off_t)-(off << imp->im_bshift), NULL,
894: &bp2);
895: else
896: bp2 = NULL;
897: cd9660_defattr(isodir, ip, bp2);
898: cd9660_deftstamp(isodir, ip, bp2);
899: if (bp2)
900: brelse(bp2);
901: break;
902: }
903: case ISO_FTYPE_RRIP:
904: cd9660_rrip_analyze(isodir, ip, imp);
905: break;
906: }
907:
908: if (bp != 0)
909: brelse(bp);
910:
911: /*
912: * Initialize the associated vnode
913: */
914: switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
915: case VFIFO:
916: vp->v_op = cd9660_fifoop_p;
917: break;
918: case VCHR:
919: case VBLK:
920: /*
921: * if device, look at device number table for translation
922: */
923: #ifdef ISODEVMAP
924: if ((dp = iso_dmap(dev, ino, 0)) != NULL)
925: ip->inode.iso_rdev = dp->d_dev;
926: #endif
927: vp->v_op = cd9660_specop_p;
928: if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
929: /*
930: * Discard unneeded vnode, but save its iso_node.
931: * Note that the lock is carried over in the iso_node
932: * to the replacement vnode.
933: */
934: nvp->v_data = vp->v_data;
935: vp->v_data = NULL;
936: VOP_UNLOCK(vp, 0);
937: vp->v_op = spec_vnodeop_p;
938: vrele(vp);
939: vgone(vp);
940: lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock);
941: /*
942: * Reinitialize aliased inode.
943: */
944: vp = nvp;
945: ip->i_vnode = vp;
946: }
947: break;
948: case VLNK:
949: case VNON:
950: case VSOCK:
951: case VDIR:
952: case VBAD:
953: break;
954: case VREG:
955: uvm_vnp_setsize(vp, ip->i_size);
956: break;
957: }
958:
959: if (ip->iso_extent == imp->root_extent)
960: vp->v_flag |= VROOT;
961:
962: /*
963: * XXX need generation number?
964: */
965:
966: genfs_node_init(vp, &cd9660_genfsops);
967: *vpp = vp;
968: return (0);
969: }
970:
971: /*
972: * Vnode pointer to File handle
973: */
974: /* ARGSUSED */
975: int
976: cd9660_vptofh(vp, fhp)
977: struct vnode *vp;
978: struct fid *fhp;
979: {
980: struct iso_node *ip = VTOI(vp);
981: struct ifid *ifhp;
982:
983: ifhp = (struct ifid *)fhp;
984: ifhp->ifid_len = sizeof(struct ifid);
985:
986: ifhp->ifid_ino = ip->i_number;
987: ifhp->ifid_start = ip->iso_start;
988:
989: #ifdef ISOFS_DBG
990: printf("vptofh: ino %d, start %ld\n",
991: ifhp->ifid_ino,ifhp->ifid_start);
992: #endif
993: return 0;
994: }
995:
996: int
1.6 ! darrenr 997: cd9660_sysctl(name, namelen, oldp, oldlenp, newp, newlen, l)
1.1 jdolecek 998: int *name;
999: u_int namelen;
1000: void *oldp;
1001: size_t *oldlenp;
1002: void *newp;
1003: size_t newlen;
1.6 ! darrenr 1004: struct lwp *l;
1.1 jdolecek 1005: {
1006: return (EOPNOTSUPP);
1007: }
CVSweb <webmaster@jp.NetBSD.org>