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/miscfs/umapfs/umap_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 /*
    2  * Copyright (c) 1992, 1993, 1995
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software donated to Berkeley by
    6  * the UCLA Ficus project.
    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 the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. 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  *      @(#)umap_vfsops.c       8.8 (Berkeley) 5/14/95
   37  *
   38  * $FreeBSD$
   39  */
   40 
   41 /*
   42  * Umap Layer
   43  * (See mount_umap(8) for a description of this layer.)
   44  */
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/proc.h>
   50 #include <sys/vnode.h>
   51 #include <sys/mount.h>
   52 #include <sys/namei.h>
   53 #include <sys/malloc.h>
   54 #include <miscfs/umapfs/umap.h>
   55 
   56 static MALLOC_DEFINE(M_UMAPFSMNT, "UMAP mount", "UMAP mount structure");
   57 
   58 static int      umapfs_fhtovp __P((struct mount *mp, struct fid *fidp,
   59                                    struct sockaddr *nam, struct vnode **vpp,
   60                                    int *exflagsp, struct ucred **credanonp));
   61 static int      umapfs_mount __P((struct mount *mp, char *path, caddr_t data,
   62                                   struct nameidata *ndp, struct proc *p));
   63 static int      umapfs_quotactl __P((struct mount *mp, int cmd, uid_t uid,
   64                                      caddr_t arg, struct proc *p));
   65 static int      umapfs_root __P((struct mount *mp, struct vnode **vpp));
   66 static int      umapfs_start __P((struct mount *mp, int flags, struct proc *p));
   67 static int      umapfs_statfs __P((struct mount *mp, struct statfs *sbp,
   68                                    struct proc *p));
   69 static int      umapfs_sync __P((struct mount *mp, int waitfor,
   70                                  struct ucred *cred, struct proc *p));
   71 static int      umapfs_unmount __P((struct mount *mp, int mntflags,
   72                                     struct proc *p));
   73 static int      umapfs_vget __P((struct mount *mp, ino_t ino,
   74                                  struct vnode **vpp));
   75 static int      umapfs_vptofh __P((struct vnode *vp, struct fid *fhp));
   76 
   77 /*
   78  * Mount umap layer
   79  */
   80 static int
   81 umapfs_mount(mp, path, data, ndp, p)
   82         struct mount *mp;
   83         char *path;
   84         caddr_t data;
   85         struct nameidata *ndp;
   86         struct proc *p;
   87 {
   88         struct umap_args args;
   89         struct vnode *lowerrootvp, *vp;
   90         struct vnode *umapm_rootvp;
   91         struct umap_mount *amp;
   92         u_int size;
   93         int error;
   94 #ifdef UMAP_DIAGNOSTIC
   95         int     i;
   96 #endif
   97 
   98 #ifdef UMAPFS_DIAGNOSTIC
   99         printf("umapfs_mount(mp = %x)\n", mp);
  100 #endif
  101 
  102         /*
  103          * Update is a no-op
  104          */
  105         if (mp->mnt_flag & MNT_UPDATE) {
  106                 return (EOPNOTSUPP);
  107                 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
  108         }
  109 
  110         /*
  111          * Get argument
  112          */
  113         error = copyin(data, (caddr_t)&args, sizeof(struct umap_args));
  114         if (error)
  115                 return (error);
  116 
  117         /*
  118          * Find lower node
  119          */
  120         NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
  121                 UIO_USERSPACE, args.target, p);
  122         error = namei(ndp);
  123         if (error)
  124                 return (error);
  125 
  126         /*
  127          * Sanity check on lower vnode
  128          */
  129         lowerrootvp = ndp->ni_vp;
  130 #ifdef UMAPFS_DIAGNOSTIC
  131         printf("vp = %x, check for VDIR...\n", lowerrootvp);
  132 #endif
  133         vrele(ndp->ni_dvp);
  134         ndp->ni_dvp = 0;
  135 
  136         if (lowerrootvp->v_type != VDIR) {
  137                 vput(lowerrootvp);
  138                 return (EINVAL);
  139         }
  140 
  141 #ifdef UMAPFS_DIAGNOSTIC
  142         printf("mp = %x\n", mp);
  143 #endif
  144 
  145         amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
  146                                 M_UMAPFSMNT, M_WAITOK); /* XXX */
  147 
  148         /*
  149          * Save reference to underlying FS
  150          */
  151         amp->umapm_vfs = lowerrootvp->v_mount;
  152 
  153         /*
  154          * Now copy in the number of entries and maps for umap mapping.
  155          */
  156         amp->info_nentries = args.nentries;
  157         amp->info_gnentries = args.gnentries;
  158         error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
  159             2*sizeof(u_long)*args.nentries);
  160         if (error)
  161                 return (error);
  162 
  163 #ifdef UMAP_DIAGNOSTIC
  164         printf("umap_mount:nentries %d\n",args.nentries);
  165         for (i = 0; i < args.nentries; i++)
  166                 printf("   %d maps to %d\n", amp->info_mapdata[i][0],
  167                     amp->info_mapdata[i][1]);
  168 #endif
  169 
  170         error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
  171             2*sizeof(u_long)*args.gnentries);
  172         if (error)
  173                 return (error);
  174 
  175 #ifdef UMAP_DIAGNOSTIC
  176         printf("umap_mount:gnentries %d\n",args.gnentries);
  177         for (i = 0; i < args.gnentries; i++)
  178                 printf("        group %d maps to %d\n",
  179                     amp->info_gmapdata[i][0],
  180                     amp->info_gmapdata[i][1]);
  181 #endif
  182 
  183 
  184         /*
  185          * Save reference.  Each mount also holds
  186          * a reference on the root vnode.
  187          */
  188         error = umap_node_create(mp, lowerrootvp, &vp);
  189         /*
  190          * Unlock the node (either the lower or the alias)
  191          */
  192         VOP_UNLOCK(vp, 0, p);
  193         /*
  194          * Make sure the node alias worked
  195          */
  196         if (error) {
  197                 vrele(lowerrootvp);
  198                 free(amp, M_UMAPFSMNT); /* XXX */
  199                 return (error);
  200         }
  201 
  202         /*
  203          * Keep a held reference to the root vnode.
  204          * It is vrele'd in umapfs_unmount.
  205          */
  206         umapm_rootvp = vp;
  207         umapm_rootvp->v_flag |= VROOT;
  208         amp->umapm_rootvp = umapm_rootvp;
  209         if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
  210                 mp->mnt_flag |= MNT_LOCAL;
  211         mp->mnt_data = (qaddr_t) amp;
  212         vfs_getnewfsid(mp);
  213 
  214         (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
  215         bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
  216         (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
  217             &size);
  218         bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  219         (void)umapfs_statfs(mp, &mp->mnt_stat, p);
  220 #ifdef UMAPFS_DIAGNOSTIC
  221         printf("umapfs_mount: lower %s, alias at %s\n",
  222                 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
  223 #endif
  224         return (0);
  225 }
  226 
  227 /*
  228  * VFS start.  Nothing needed here - the start routine
  229  * on the underlying filesystem will have been called
  230  * when that filesystem was mounted.
  231  */
  232 static int
  233 umapfs_start(mp, flags, p)
  234         struct mount *mp;
  235         int flags;
  236         struct proc *p;
  237 {
  238         return (0);
  239         /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
  240 }
  241 
  242 /*
  243  * Free reference to umap layer
  244  */
  245 static int
  246 umapfs_unmount(mp, mntflags, p)
  247         struct mount *mp;
  248         int mntflags;
  249         struct proc *p;
  250 {
  251         struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
  252         int error;
  253         int flags = 0;
  254 
  255 #ifdef UMAPFS_DIAGNOSTIC
  256         printf("umapfs_unmount(mp = %x)\n", mp);
  257 #endif
  258 
  259         if (mntflags & MNT_FORCE)
  260                 flags |= FORCECLOSE;
  261 
  262         /*
  263          * Clear out buffer cache.  I don't think we
  264          * ever get anything cached at this level at the
  265          * moment, but who knows...
  266          */
  267 #ifdef notyet
  268         mntflushbuf(mp, 0);
  269         if (mntinvalbuf(mp, 1))
  270                 return (EBUSY);
  271 #endif
  272         if (umapm_rootvp->v_usecount > 1)
  273                 return (EBUSY);
  274         error = vflush(mp, umapm_rootvp, flags);
  275         if (error)
  276                 return (error);
  277 
  278 #ifdef UMAPFS_DIAGNOSTIC
  279         vprint("alias root of lower", umapm_rootvp);
  280 #endif
  281         /*
  282          * Release reference on underlying root vnode
  283          */
  284         vrele(umapm_rootvp);
  285         /*
  286          * And blow it away for future re-use
  287          */
  288         vgone(umapm_rootvp);
  289         /*
  290          * Finally, throw away the umap_mount structure
  291          */
  292         free(mp->mnt_data, M_UMAPFSMNT);        /* XXX */
  293         mp->mnt_data = 0;
  294         return (0);
  295 }
  296 
  297 static int
  298 umapfs_root(mp, vpp)
  299         struct mount *mp;
  300         struct vnode **vpp;
  301 {
  302         struct proc *p = curproc;       /* XXX */
  303         struct vnode *vp;
  304 
  305 #ifdef UMAPFS_DIAGNOSTIC
  306         printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
  307                         MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
  308                         UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
  309                         );
  310 #endif
  311 
  312         /*
  313          * Return locked reference to root.
  314          */
  315         vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
  316         VREF(vp);
  317         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  318         *vpp = vp;
  319         return (0);
  320 }
  321 
  322 static int
  323 umapfs_quotactl(mp, cmd, uid, arg, p)
  324         struct mount *mp;
  325         int cmd;
  326         uid_t uid;
  327         caddr_t arg;
  328         struct proc *p;
  329 {
  330         return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
  331 }
  332 
  333 static int
  334 umapfs_statfs(mp, sbp, p)
  335         struct mount *mp;
  336         struct statfs *sbp;
  337         struct proc *p;
  338 {
  339         int error;
  340         struct statfs mstat;
  341 
  342 #ifdef UMAPFS_DIAGNOSTIC
  343         printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
  344                         MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
  345                         UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
  346                         );
  347 #endif
  348 
  349         bzero(&mstat, sizeof(mstat));
  350 
  351         error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
  352         if (error)
  353                 return (error);
  354 
  355         /* now copy across the "interesting" information and fake the rest */
  356         sbp->f_type = mstat.f_type;
  357         sbp->f_flags = mstat.f_flags;
  358         sbp->f_bsize = mstat.f_bsize;
  359         sbp->f_iosize = mstat.f_iosize;
  360         sbp->f_blocks = mstat.f_blocks;
  361         sbp->f_bfree = mstat.f_bfree;
  362         sbp->f_bavail = mstat.f_bavail;
  363         sbp->f_files = mstat.f_files;
  364         sbp->f_ffree = mstat.f_ffree;
  365         if (sbp != &mp->mnt_stat) {
  366                 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
  367                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  368                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  369         }
  370         return (0);
  371 }
  372 
  373 static int
  374 umapfs_sync(mp, waitfor, cred, p)
  375         struct mount *mp;
  376         int waitfor;
  377         struct ucred *cred;
  378         struct proc *p;
  379 {
  380         /*
  381          * XXX - Assumes no data cached at umap layer.
  382          */
  383         return (0);
  384 }
  385 
  386 static int
  387 umapfs_vget(mp, ino, vpp)
  388         struct mount *mp;
  389         ino_t ino;
  390         struct vnode **vpp;
  391 {
  392 
  393         return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
  394 }
  395 
  396 static int
  397 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
  398         struct mount *mp;
  399         struct fid *fidp;
  400         struct sockaddr *nam;
  401         struct vnode **vpp;
  402         int *exflagsp;
  403         struct ucred**credanonp;
  404 {
  405 
  406         return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
  407 }
  408 
  409 static int
  410 umapfs_vptofh(vp, fhp)
  411         struct vnode *vp;
  412         struct fid *fhp;
  413 {
  414         return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
  415 }
  416 
  417 static struct vfsops umap_vfsops = {
  418         umapfs_mount,
  419         umapfs_start,
  420         umapfs_unmount,
  421         umapfs_root,
  422         umapfs_quotactl,
  423         umapfs_statfs,
  424         umapfs_sync,
  425         umapfs_vget,
  426         umapfs_fhtovp,
  427         umapfs_vptofh,
  428         umapfs_init,
  429 };
  430 
  431 VFS_SET(umap_vfsops, umap, VFCF_LOOPBACK);

Cache object: 3f7c0d92255cc0d88a6f27297dfb11ba


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