[BACK]Return to cd9660_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / cd9660

Annotation of src/sys/fs/cd9660/cd9660_vfsops.c, Revision 1.8.2.5

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

CVSweb <webmaster@jp.NetBSD.org>