The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/cd9660/cd9660_vfsops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a701daed2a9af4dfb96fbf306d8c52cd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.