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

Cache object: 01d9ca83d4cc5d07360712b3343ab8da


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