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/adosfs/advfsops.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: advfsops.c,v 1.11.2.1 2004/05/29 09:03:28 tron Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1994 Christian E. Hopps
    5  * Copyright (c) 1996 Matthias Scheler
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Christian E. Hopps.
   19  * 4. The name of the author may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: advfsops.c,v 1.11.2.1 2004/05/29 09:03:28 tron Exp $");
   36 
   37 #if defined(_KERNEL_OPT)
   38 #include "opt_compat_netbsd.h"
   39 #endif
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/vnode.h>
   45 #include <sys/mount.h>
   46 #include <sys/proc.h>
   47 #include <sys/time.h>
   48 #include <sys/malloc.h>
   49 #include <sys/pool.h>
   50 #include <sys/disklabel.h>
   51 #include <miscfs/specfs/specdev.h> /* XXX */
   52 #include <sys/fcntl.h>
   53 #include <sys/namei.h>
   54 #include <sys/ioctl.h>
   55 #include <sys/queue.h>
   56 #include <sys/buf.h>
   57 #include <sys/conf.h>
   58 #include <fs/adosfs/adosfs.h>
   59 
   60 void adosfs_init __P((void));
   61 void adosfs_reinit __P((void));
   62 void adosfs_done __P((void));
   63 int adosfs_mount __P((struct mount *, const char *, void *, struct nameidata *,
   64                       struct proc *));
   65 int adosfs_start __P((struct mount *, int, struct proc *));
   66 int adosfs_unmount __P((struct mount *, int, struct proc *));
   67 int adosfs_root __P((struct mount *, struct vnode **));
   68 int adosfs_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
   69 int adosfs_statfs __P((struct mount *, struct statfs *, struct proc *));
   70 int adosfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
   71 int adosfs_vget __P((struct mount *, ino_t, struct vnode **));
   72 int adosfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
   73 int adosfs_checkexp __P((struct mount *, struct mbuf *, int *,
   74                        struct ucred **));
   75 int adosfs_vptofh __P((struct vnode *, struct fid *));
   76 
   77 int adosfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
   78 int adosfs_loadbitmap __P((struct adosfsmount *));
   79 
   80 struct simplelock adosfs_hashlock;
   81 
   82 struct pool adosfs_node_pool;
   83 
   84 MALLOC_DEFINE(M_ADOSFSMNT, "adosfs mount", "adosfs mount structures");
   85 MALLOC_DEFINE(M_ANODE, "adosfs anode", "adosfs anode structures and tables");
   86 MALLOC_DEFINE(M_ADOSFSBITMAP, "adosfs bitmap", "adosfs bitmap");
   87 
   88 struct genfs_ops adosfs_genfsops = {
   89         genfs_size,
   90 };
   91 
   92 int (**adosfs_vnodeop_p) __P((void *));
   93 
   94 int
   95 adosfs_mount(mp, path, data, ndp, p)
   96         struct mount *mp;
   97         const char *path;
   98         void *data;
   99         struct nameidata *ndp;
  100         struct proc *p;
  101 {
  102         struct vnode *devvp;
  103         struct adosfs_args args;
  104         struct adosfsmount *amp;
  105         int error;
  106         mode_t accessmode;
  107 
  108         if (mp->mnt_flag & MNT_GETARGS) {
  109                 amp = VFSTOADOSFS(mp);
  110                 if (amp == NULL)
  111                         return EIO;
  112                 args.uid = amp->uid;
  113                 args.gid = amp->gid;
  114                 args.mask = amp->mask;
  115                 args.fspec = NULL;
  116                 vfs_showexport(mp, &args.export, &amp->export);
  117                 return copyout(&args, data, sizeof(args));
  118         }
  119         error = copyin(data, &args, sizeof(struct adosfs_args));
  120         if (error)
  121                 return(error);
  122         
  123         if ((mp->mnt_flag & MNT_RDONLY) == 0)
  124                 return (EROFS);
  125         /*
  126          * If updating, check whether changing from read-only to
  127          * read/write; if there is no device name, that's all we do.
  128          */
  129         if (mp->mnt_flag & MNT_UPDATE) {
  130                 amp = VFSTOADOSFS(mp);
  131                 if (args.fspec == 0)
  132                         return (vfs_export(mp, &amp->export, &args.export));
  133         }
  134         /*
  135          * Not an update, or updating the name: look up the name
  136          * and verify that it refers to a sensible block device.
  137          */
  138         NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
  139         if ((error = namei(ndp)) != 0)
  140                 return (error);
  141         devvp = ndp->ni_vp;
  142 
  143         if (devvp->v_type != VBLK) {
  144                 vrele(devvp);
  145                 return (ENOTBLK);
  146         }
  147         if (bdevsw_lookup(devvp->v_rdev) == NULL) {
  148                 vrele(devvp);
  149                 return (ENXIO);
  150         }
  151         /*
  152          * If mount by non-root, then verify that user has necessary
  153          * permissions on the device.
  154          */
  155         if (p->p_ucred->cr_uid != 0) {
  156                 accessmode = VREAD;
  157                 if ((mp->mnt_flag & MNT_RDONLY) == 0)
  158                         accessmode |= VWRITE;
  159                 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  160                 error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
  161                 if (error) {
  162                         vput(devvp);
  163                         return (error);
  164                 }
  165                 VOP_UNLOCK(devvp, 0);
  166         }
  167 /* MNT_UPDATE? */
  168         if ((error = adosfs_mountfs(devvp, mp, p)) != 0) {
  169                 vrele(devvp);
  170                 return (error);
  171         }
  172         amp = VFSTOADOSFS(mp);
  173         amp->uid = args.uid;
  174         amp->gid = args.gid;
  175         amp->mask = args.mask;
  176         return set_statfs_info(path, UIO_USERSPACE, args.fspec, UIO_USERSPACE,
  177             mp, p);
  178 }
  179 
  180 int
  181 adosfs_mountfs(devvp, mp, p)
  182         struct vnode *devvp;
  183         struct mount *mp;
  184         struct proc *p;
  185 {
  186         struct disklabel dl;
  187         struct partition *parp;
  188         struct adosfsmount *amp;
  189         struct buf *bp;
  190         struct vnode *rvp;
  191         int error, part, i;
  192 
  193         part = DISKPART(devvp->v_rdev);
  194         amp = NULL;
  195 
  196         /*
  197          * Disallow multiple mounts of the same device.
  198          * Disallow mounting of a device that is currently in use
  199          * (except for root, which might share swap device for miniroot).
  200          * Flush out any old buffers remaining from a previous use.
  201          */
  202         if ((error = vfs_mountedon(devvp)) != 0)
  203                 return (error);
  204         if (vcount(devvp) > 1 && devvp != rootvp)
  205                 return (EBUSY);
  206         if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
  207                 return (error);
  208 
  209         /* 
  210          * open blkdev and read root block
  211          */
  212         if ((error = VOP_OPEN(devvp, FREAD, NOCRED, p)) != 0)
  213                 return (error);
  214         error = VOP_IOCTL(devvp, DIOCGDINFO, &dl, FREAD, NOCRED, p);
  215         if (error)
  216                 goto fail;
  217 
  218         parp = &dl.d_partitions[part];
  219         amp = malloc(sizeof(struct adosfsmount), M_ADOSFSMNT, M_WAITOK);
  220         memset((char *)amp, 0, (u_long)sizeof(struct adosfsmount));
  221         amp->mp = mp;
  222         if (dl.d_type == DTYPE_FLOPPY) {
  223                 amp->bsize = dl.d_secsize;
  224                 amp->secsperblk = 1;
  225         }
  226         else {
  227                 amp->bsize = parp->p_fsize * parp->p_frag;
  228                 amp->secsperblk = parp->p_frag;
  229         }
  230 
  231         /* invalid fs ? */
  232         if (amp->secsperblk == 0) {
  233                 error = EINVAL;
  234                 goto fail;
  235         }
  236 
  237         bp = NULL;
  238         if ((error = bread(devvp, (daddr_t)BBOFF,
  239                            amp->bsize, NOCRED, &bp)) != 0) {
  240                 brelse(bp);
  241                 goto fail;
  242         }
  243         amp->dostype = adoswordn(bp, 0);
  244         brelse(bp);
  245 
  246         /* basic sanity checks */
  247         if (amp->dostype < 0x444f5300 || amp->dostype > 0x444f5305) {
  248                 error = EINVAL;
  249                 goto fail;
  250         }
  251 
  252         amp->rootb = (parp->p_size / amp->secsperblk - 1 + parp->p_cpg) >> 1;
  253         amp->numblks = parp->p_size / amp->secsperblk - parp->p_cpg;
  254 
  255         amp->nwords = amp->bsize >> 2;
  256         amp->dbsize = amp->bsize - (IS_FFS(amp) ? 0 : OFS_DATA_OFFSET);
  257         amp->devvp = devvp;
  258         
  259         mp->mnt_data = amp;
  260         mp->mnt_stat.f_fsid.val[0] = (long)devvp->v_rdev;
  261         mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_ADOSFS);
  262         mp->mnt_fs_bshift = ffs(amp->bsize) - 1;
  263         mp->mnt_dev_bshift = DEV_BSHIFT;        /* XXX */
  264         mp->mnt_flag |= MNT_LOCAL;
  265 
  266         /*
  267          * init anode table.
  268          */
  269         for (i = 0; i < ANODEHASHSZ; i++) 
  270                 LIST_INIT(&amp->anodetab[i]);
  271 
  272         /*
  273          * get the root anode, if not a valid fs this will fail.
  274          */
  275         if ((error = VFS_ROOT(mp, &rvp)) != 0)
  276                 goto fail;
  277         /* allocate and load bitmap, set free space */
  278         amp->bitmap = malloc(((amp->numblks + 31) / 32) * sizeof(*amp->bitmap),
  279             M_ADOSFSBITMAP, M_WAITOK);
  280         if (amp->bitmap)
  281                 adosfs_loadbitmap(amp);
  282         if (mp->mnt_flag & MNT_RDONLY && amp->bitmap) {
  283                 /*
  284                  * Don't need the bitmap any more if it's read-only.
  285                  */
  286                 free(amp->bitmap, M_ADOSFSBITMAP);
  287                 amp->bitmap = NULL;
  288         }
  289         vput(rvp);
  290 
  291         return(0);
  292 
  293 fail:
  294         vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
  295         (void) VOP_CLOSE(devvp, FREAD, NOCRED, p);
  296         VOP_UNLOCK(devvp, 0);
  297         if (amp && amp->bitmap)
  298                 free(amp->bitmap, M_ADOSFSBITMAP);
  299         if (amp)
  300                 free(amp, M_ADOSFSMNT);
  301         return (error);
  302 }
  303 
  304 int
  305 adosfs_start(mp, flags, p)
  306         struct mount *mp;
  307         int flags;
  308         struct proc *p;
  309 {
  310 
  311         return (0);
  312 }
  313 
  314 int
  315 adosfs_unmount(mp, mntflags, p)
  316         struct mount *mp;
  317         int mntflags;
  318         struct proc *p;
  319 {
  320         struct adosfsmount *amp;
  321         int error, flags;
  322 
  323         flags = 0;
  324         if (mntflags & MNT_FORCE)
  325                 flags |= FORCECLOSE;
  326         if ((error = vflush(mp, NULLVP, flags)) != 0)
  327                 return (error);
  328         amp = VFSTOADOSFS(mp);
  329         if (amp->devvp->v_type != VBAD)
  330                 amp->devvp->v_specmountpoint = NULL;
  331         vn_lock(amp->devvp, LK_EXCLUSIVE | LK_RETRY);
  332         error = VOP_CLOSE(amp->devvp, FREAD, NOCRED, p);
  333         vput(amp->devvp);
  334         if (amp->bitmap)
  335                 free(amp->bitmap, M_ADOSFSBITMAP);
  336         free(amp, M_ADOSFSMNT);
  337         mp->mnt_data = NULL;
  338         mp->mnt_flag &= ~MNT_LOCAL;
  339         return (error);
  340 }
  341 
  342 int
  343 adosfs_root(mp, vpp)
  344         struct mount *mp;
  345         struct vnode **vpp;
  346 {
  347         struct vnode *nvp;
  348         int error;
  349 
  350         if ((error = VFS_VGET(mp, (ino_t)VFSTOADOSFS(mp)->rootb, &nvp)) != 0)
  351                 return (error);
  352         /* XXX verify it's a root block? */
  353         *vpp = nvp;
  354         return (0);
  355 }
  356 
  357 int
  358 adosfs_statfs(mp, sbp, p)
  359         struct mount *mp;
  360         struct statfs *sbp;
  361         struct proc *p;
  362 {
  363         struct adosfsmount *amp;
  364 
  365         amp = VFSTOADOSFS(mp);
  366 #ifdef COMPAT_09
  367         sbp->f_type = 16;
  368 #else
  369         sbp->f_type = 0;
  370 #endif
  371         sbp->f_bsize = amp->bsize;
  372         sbp->f_iosize = amp->dbsize;
  373         sbp->f_blocks = amp->numblks;
  374         sbp->f_bfree = amp->freeblks;
  375         sbp->f_bavail = amp->freeblks;
  376         sbp->f_files = 0;               /* who knows */
  377         sbp->f_ffree = 0;               /* " " */
  378         copy_statfs_info(sbp, mp);
  379         return (0);
  380 }
  381 
  382 /* 
  383  * lookup an anode, check mount's hash table if not found, create
  384  * return locked and referenced al la vget(vp, 1);
  385  */
  386 int
  387 adosfs_vget(mp, an, vpp)
  388         struct mount *mp;
  389         ino_t an;
  390         struct vnode **vpp;
  391 {
  392         struct adosfsmount *amp;
  393         struct vnode *vp;
  394         struct anode *ap;
  395         struct buf *bp;
  396         char *nam, *tmp;
  397         int namlen, error;
  398 
  399         error = 0;
  400         amp = VFSTOADOSFS(mp);
  401         bp = NULL;
  402 
  403         /* 
  404          * check hash table. we are done if found
  405          */
  406         if ((*vpp = adosfs_ahashget(mp, an)) != NULL)
  407                 return (0);
  408 
  409         error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, &vp);
  410         if (error)
  411                 return (error);
  412 
  413         /*
  414          * setup, insert in hash, and lock before io.
  415          */
  416         vp->v_data = ap = pool_get(&adosfs_node_pool, PR_WAITOK);
  417         memset(ap, 0, sizeof(struct anode));
  418         ap->vp = vp;
  419         ap->amp = amp;
  420         ap->block = an;
  421         ap->nwords = amp->nwords;
  422         adosfs_ainshash(amp, ap);
  423 
  424         if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE,
  425                            amp->bsize, NOCRED, &bp)) != 0) {
  426                 brelse(bp);
  427                 vput(vp);
  428                 return (error);
  429         }
  430 
  431         /*
  432          * get type and fill rest in based on that.
  433          */
  434         switch (ap->type = adosfs_getblktype(amp, bp)) {
  435         case AROOT:
  436                 vp->v_type = VDIR;
  437                 vp->v_flag |= VROOT;
  438                 ap->mtimev.days = adoswordn(bp, ap->nwords - 10);
  439                 ap->mtimev.mins = adoswordn(bp, ap->nwords - 9);
  440                 ap->mtimev.ticks = adoswordn(bp, ap->nwords - 8);
  441                 ap->created.days = adoswordn(bp, ap->nwords - 7);
  442                 ap->created.mins = adoswordn(bp, ap->nwords - 6);
  443                 ap->created.ticks = adoswordn(bp, ap->nwords - 5);
  444                 break;
  445         case ALDIR:
  446         case ADIR:
  447                 vp->v_type = VDIR;
  448                 break;
  449         case ALFILE:
  450         case AFILE:
  451                 vp->v_type = VREG;
  452                 ap->fsize = adoswordn(bp, ap->nwords - 47);
  453                 break;
  454         case ASLINK:            /* XXX soft link */
  455                 vp->v_type = VLNK;
  456                 /*
  457                  * convert from BCPL string and
  458                  * from: "part:dir/file" to: "/part/dir/file"
  459                  */
  460                 nam = bp->b_data + (6 * sizeof(long));
  461                 namlen = strlen(nam);
  462                 tmp = nam;
  463                 while (*tmp && *tmp != ':')
  464                         tmp++;
  465                 if (*tmp == 0) {
  466                         ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK);
  467                         memcpy(ap->slinkto, nam, namlen);
  468                 } else if (*nam == ':') {
  469                         ap->slinkto = malloc(namlen + 1, M_ANODE, M_WAITOK);
  470                         memcpy(ap->slinkto, nam, namlen);
  471                         ap->slinkto[0] = '/';
  472                 } else {
  473                         ap->slinkto = malloc(namlen + 2, M_ANODE, M_WAITOK);
  474                         ap->slinkto[0] = '/';
  475                         memcpy(&ap->slinkto[1], nam, namlen);
  476                         ap->slinkto[tmp - nam + 1] = '/';
  477                         namlen++;
  478                 }
  479                 ap->slinkto[namlen] = 0;
  480                 ap->fsize = namlen;
  481                 break;
  482         default:
  483                 brelse(bp);
  484                 vput(vp);
  485                 return (EINVAL);
  486         }
  487 
  488         /*
  489          * Get appropriate data from this block;  hard link needs
  490          * to get other data from the "real" block.
  491          */
  492 
  493         /*
  494          * copy in name (from original block)
  495          */
  496         nam = bp->b_data + (ap->nwords - 20) * sizeof(u_int32_t);
  497         namlen = *(u_char *)nam++;
  498         if (namlen > 30) {
  499 #ifdef DIAGNOSTIC
  500                 printf("adosfs: aget: name length too long blk %d\n", an);
  501 #endif
  502                 brelse(bp);
  503                 vput(vp);
  504                 return (EINVAL);
  505         }
  506         memcpy(ap->name, nam, namlen);
  507         ap->name[namlen] = 0;
  508 
  509         /* 
  510          * if dir alloc hash table and copy it in 
  511          */
  512         if (vp->v_type == VDIR) {
  513                 int i;
  514 
  515                 ap->tab = malloc(ANODETABSZ(ap) * 2, M_ANODE, M_WAITOK);
  516                 ap->ntabent = ANODETABENT(ap);
  517                 ap->tabi = (int *)&ap->tab[ap->ntabent];
  518                 memset(ap->tabi, 0, ANODETABSZ(ap));
  519                 for (i = 0; i < ap->ntabent; i++)
  520                         ap->tab[i] = adoswordn(bp, i + 6);
  521         }
  522 
  523         /*
  524          * misc.
  525          */
  526         ap->pblock = adoswordn(bp, ap->nwords - 3);
  527         ap->hashf = adoswordn(bp, ap->nwords - 4);
  528         ap->linknext = adoswordn(bp, ap->nwords - 10);
  529         ap->linkto = adoswordn(bp, ap->nwords - 11);
  530 
  531         /*
  532          * setup last indirect block cache.
  533          */
  534         ap->lastlindblk = 0;
  535         if (ap->type == AFILE)  {
  536                 ap->lastindblk = ap->block;
  537                 if (adoswordn(bp, ap->nwords - 10))
  538                         ap->linkto = ap->block;
  539         } else if (ap->type == ALFILE) {
  540                 ap->lastindblk = ap->linkto;
  541                 brelse(bp);
  542                 bp = NULL;
  543                 error = bread(amp->devvp, ap->linkto * amp->bsize / DEV_BSIZE,
  544                     amp->bsize, NOCRED, &bp);
  545                 if (error) {
  546                         brelse(bp);
  547                         vput(vp);
  548                         return (error);
  549                 }
  550                 ap->fsize = adoswordn(bp, ap->nwords - 47);
  551                 /*
  552                  * Should ap->block be set to the real file header block?
  553                  */
  554                 ap->block = ap->linkto;
  555         }
  556 
  557         if (ap->type == AROOT) {
  558                 ap->adprot = 15;
  559                 ap->uid = amp->uid;
  560                 ap->gid = amp->gid;
  561         } else {
  562                 ap->adprot = adoswordn(bp, ap->nwords - 48) ^ 15;
  563                 /*
  564                  * ADOS directories do not have a `x' protection bit as
  565                  * it is known in VFS; this functionality is fulfilled
  566                  * by the ADOS `r' bit.
  567                  *
  568                  * To retain the ADOS behaviour, fake execute permissions
  569                  * in that case.
  570                  */
  571                 if ((ap->type == ADIR || ap->type == ALDIR) &&
  572                     (ap->adprot & 0x00000008) == 0)
  573                         ap->adprot &= ~0x00000002;
  574 
  575                 /*
  576                  * Get uid/gid from extensions in file header
  577                  * (really need to know if this is a muFS partition)
  578                  */
  579                 ap->uid = (adoswordn(bp, ap->nwords - 49) >> 16) & 0xffff;
  580                 ap->gid = adoswordn(bp, ap->nwords - 49) & 0xffff;
  581                 if (ap->uid || ap->gid) {
  582                         if (ap->uid == 0xffff)
  583                                 ap->uid = 0;
  584                         if (ap->gid == 0xffff)
  585                                 ap->gid = 0;
  586                         ap->adprot |= 0x40000000;       /* Kludge */
  587                 }
  588                 else {
  589                         /*
  590                          * uid & gid extension don't exist,
  591                          * so use the mount-point uid/gid
  592                          */
  593                         ap->uid = amp->uid;
  594                         ap->gid = amp->gid;
  595                 }
  596         }
  597         ap->mtime.days = adoswordn(bp, ap->nwords - 23);
  598         ap->mtime.mins = adoswordn(bp, ap->nwords - 22);
  599         ap->mtime.ticks = adoswordn(bp, ap->nwords - 21);
  600 
  601         genfs_node_init(vp, &adosfs_genfsops);
  602         *vpp = vp;
  603         brelse(bp);
  604         vp->v_size = ap->fsize;
  605         return (0);
  606 }
  607 
  608 /*
  609  * Load the bitmap into memory, and count the number of available
  610  * blocks.
  611  * The bitmap will be released if the filesystem is read-only;  it's
  612  * only needed to find the free space.
  613  */
  614 int
  615 adosfs_loadbitmap(amp)
  616         struct adosfsmount *amp;
  617 {
  618         struct buf *bp, *mapbp;
  619         u_long bn;
  620         int blkix, endix, mapix;
  621         int bmsize;
  622         int error;
  623 
  624         bp = mapbp = NULL;
  625         bn = amp->rootb;
  626         if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE, amp->bsize,
  627             NOCRED, &bp)) != 0) {
  628                 brelse(bp);
  629                 return (error);
  630         }
  631         blkix = amp->nwords - 49;
  632         endix = amp->nwords - 24;
  633         mapix = 0;
  634         bmsize = (amp->numblks + 31) / 32;
  635         while (mapix < bmsize) {
  636                 int n;
  637                 u_long bits;
  638 
  639                 if (adoswordn(bp, blkix) == 0)
  640                         break;
  641                 if (mapbp != NULL)
  642                         brelse(mapbp);
  643                 if ((error = bread(amp->devvp,
  644                     adoswordn(bp, blkix) * amp->bsize / DEV_BSIZE, amp->bsize,
  645                      NOCRED, &mapbp)) != 0)
  646                         break;
  647                 if (adoscksum(mapbp, amp->nwords)) {
  648 #ifdef DIAGNOSTIC
  649                         printf("adosfs: loadbitmap - cksum of blk %d failed\n",
  650                             adoswordn(bp, blkix));
  651 #endif
  652                         /* XXX Force read-only?  Set free space 0? */
  653                         break;
  654                 }
  655                 n = 1;
  656                 while (n < amp->nwords && mapix < bmsize) {
  657                         amp->bitmap[mapix++] = bits = adoswordn(mapbp, n);
  658                         ++n;
  659                         if (mapix == bmsize && amp->numblks & 31)
  660                                 bits &= ~(0xffffffff << (amp->numblks & 31));
  661                         while (bits) {
  662                                 if (bits & 1)
  663                                         ++amp->freeblks;
  664                                 bits >>= 1;
  665                         }
  666                 }
  667                 ++blkix;
  668                 if (mapix < bmsize && blkix == endix) {
  669                         bn = adoswordn(bp, blkix);
  670                         brelse(bp);
  671                         if ((error = bread(amp->devvp, bn * amp->bsize / DEV_BSIZE,
  672                             amp->bsize, NOCRED, &bp)) != 0)
  673                                 break;
  674                         /*
  675                          * Why is there no checksum on these blocks?
  676                          */
  677                         blkix = 0;
  678                         endix = amp->nwords - 1;
  679                 }
  680         }
  681         if (bp)
  682                 brelse(bp);
  683         if (mapbp)
  684                 brelse(mapbp);
  685         return (error);
  686 }
  687 
  688 
  689 /*
  690  * File handle to vnode
  691  *
  692  * Have to be really careful about stale file handles:
  693  * - check that the inode number is in range
  694  * - call iget() to get the locked inode
  695  * - check for an unallocated inode (i_mode == 0)
  696  * - check that the generation number matches
  697  */
  698 
  699 struct ifid {
  700         ushort  ifid_len;
  701         ushort  ifid_pad;
  702         int     ifid_ino;
  703         long    ifid_start;
  704 };
  705 
  706 int
  707 adosfs_fhtovp(mp, fhp, vpp)
  708         struct mount *mp;
  709         struct fid *fhp;
  710         struct vnode **vpp;
  711 {
  712         struct ifid *ifhp = (struct ifid *)fhp;
  713 #if 0
  714         struct anode *ap;
  715 #endif
  716         struct vnode *nvp;
  717         int error;
  718 
  719 #ifdef ADOSFS_DIAGNOSTIC
  720         printf("adfhtovp(%x, %x, %x)\n", mp, fhp, vpp);
  721 #endif
  722         
  723         if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
  724                 *vpp = NULLVP;
  725                 return (error);
  726         }
  727 #if 0
  728         ap = VTOA(nvp);
  729         if (ap->inode.iso_mode == 0) {
  730                 vput(nvp);
  731                 *vpp = NULLVP;
  732                 return (ESTALE);
  733         }
  734 #endif
  735         *vpp = nvp;
  736         return(0);
  737 }
  738 
  739 int
  740 adosfs_checkexp(mp, nam, exflagsp, credanonp)
  741         struct mount *mp;
  742         struct mbuf *nam;
  743         int *exflagsp;
  744         struct ucred **credanonp;
  745 {
  746         struct adosfsmount *amp = VFSTOADOSFS(mp);
  747 #if 0
  748         struct anode *ap;
  749 #endif
  750         struct netcred *np;
  751 
  752 #ifdef ADOSFS_DIAGNOSTIC
  753         printf("adcheckexp(%x, %x, %x)\n", mp, nam, exflagsp);
  754 #endif
  755         
  756         /*
  757          * Get the export permission structure for this <mp, client> tuple.
  758          */
  759         np = vfs_export_lookup(mp, &amp->export, nam);
  760         if (np == NULL)
  761                 return (EACCES);
  762 
  763         *exflagsp = np->netc_exflags;
  764         *credanonp = &np->netc_anon;
  765         return(0);
  766 }
  767 
  768 int
  769 adosfs_vptofh(vp, fhp)
  770         struct vnode *vp;
  771         struct fid *fhp;
  772 {
  773         struct anode *ap = VTOA(vp);
  774         struct ifid *ifhp;
  775 
  776         ifhp = (struct ifid *)fhp;
  777         ifhp->ifid_len = sizeof(struct ifid);
  778         
  779         ifhp->ifid_ino = ap->block;
  780         ifhp->ifid_start = ap->block;
  781         
  782 #ifdef ADOSFS_DIAGNOSTIC
  783         printf("advptofh(%x, %x)\n", vp, fhp);
  784 #endif
  785         return(0);
  786 }
  787 
  788 int
  789 adosfs_quotactl(mp, cmds, uid, arg, p)
  790         struct mount *mp;
  791         int cmds;
  792         uid_t uid;
  793         caddr_t arg;
  794         struct proc *p;
  795 {
  796         return(EOPNOTSUPP);
  797 }
  798 
  799 int
  800 adosfs_sync(mp, waitfor, uc, p)
  801         struct mount *mp;
  802         int waitfor;
  803         struct ucred *uc;
  804         struct proc *p;
  805 {
  806 #ifdef ADOSFS_DIAGNOSTIC
  807         printf("ad_sync(%x, %x)\n", mp, waitfor);
  808 #endif
  809         return(0);
  810 }
  811 
  812 void
  813 adosfs_init()
  814 {
  815 #ifdef _LKM
  816         malloc_type_attach(M_ADOSFSMNT);
  817         malloc_type_attach(M_ANODE);
  818         malloc_type_attach(M_ADOSFSBITMAP);
  819 #endif
  820         simple_lock_init(&adosfs_hashlock);
  821 
  822         pool_init(&adosfs_node_pool, sizeof(struct anode), 0, 0, 0,
  823             "adosndpl", &pool_allocator_nointr);
  824 }
  825 
  826 void
  827 adosfs_done()
  828 {
  829         pool_destroy(&adosfs_node_pool);
  830 #ifdef _LKM
  831         malloc_type_detach(M_ADOSFSBITMAP);
  832         malloc_type_detach(M_ANODE);
  833         malloc_type_detach(M_ADOSFSMNT);
  834 #endif
  835 }
  836 
  837 SYSCTL_SETUP(sysctl_vfs_adosfs_setup, "sysctl vfs.adosfs subtree setup")
  838 {
  839 
  840         sysctl_createv(clog, 0, NULL, NULL,
  841                        CTLFLAG_PERMANENT,
  842                        CTLTYPE_NODE, "vfs", NULL,
  843                        NULL, 0, NULL, 0,
  844                        CTL_VFS, CTL_EOL);
  845         sysctl_createv(clog, 0, NULL, NULL,
  846                        CTLFLAG_PERMANENT,
  847                        CTLTYPE_NODE, "adosfs",
  848                        SYSCTL_DESCR("AmigaDOS file system"),
  849                        NULL, 0, NULL, 0,
  850                        CTL_VFS, 16, CTL_EOL);
  851         /*
  852          * XXX the "16" above could be dynamic, thereby eliminating
  853          * one more instance of the "number to vfs" mapping problem,
  854          * but "16" is the order as taken from sys/mount.h
  855          */
  856 }
  857 
  858 /*
  859  * vfs generic function call table
  860  */
  861 
  862 extern const struct vnodeopv_desc adosfs_vnodeop_opv_desc; 
  863 
  864 const struct vnodeopv_desc *adosfs_vnodeopv_descs[] = {
  865         &adosfs_vnodeop_opv_desc,
  866         NULL,
  867 };
  868 
  869 struct vfsops adosfs_vfsops = {
  870         MOUNT_ADOSFS,
  871         adosfs_mount,
  872         adosfs_start,
  873         adosfs_unmount,
  874         adosfs_root,
  875         adosfs_quotactl,                
  876         adosfs_statfs,                  
  877         adosfs_sync,                    
  878         adosfs_vget,
  879         adosfs_fhtovp,                  
  880         adosfs_vptofh,                  
  881         adosfs_init,                    
  882         NULL,
  883         adosfs_done,
  884         NULL,
  885         NULL,                           /* vfs_mountroot */
  886         adosfs_checkexp,
  887         adosfs_vnodeopv_descs,
  888 };

Cache object: 5f01292664b6ca7510abbfa232050bf9


[ 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.