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_subr.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  * Jan-Simon Pendry.
    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_subr.c 8.9 (Berkeley) 5/14/95
   37  *
   38  * $FreeBSD$
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/proc.h>
   44 #include <sys/vnode.h>
   45 #include <sys/mount.h>
   46 #include <sys/malloc.h>
   47 #include <miscfs/umapfs/umap.h>
   48 
   49 #define LOG2_SIZEVNODE 7                /* log2(sizeof struct vnode) */
   50 #define NUMAPNODECACHE 16
   51 
   52 /*
   53  * Null layer cache:
   54  * Each cache entry holds a reference to the target vnode
   55  * along with a pointer to the alias vnode.  When an
   56  * entry is added the target vnode is VREF'd.  When the
   57  * alias is removed the target vnode is vrele'd.
   58  */
   59 
   60 #define UMAP_NHASH(vp) \
   61         (&umap_node_hashtbl \
   62         [((uintptr_t)(void *)(vp) >> LOG2_SIZEVNODE) & umap_node_hash])
   63 static LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
   64 static u_long umap_node_hash;
   65 
   66 static u_long   umap_findid __P((u_long id, u_long map[][2], int nentries));
   67 static int      umap_node_alloc __P((struct mount *mp, struct vnode *lowervp,
   68                                      struct vnode **vpp));
   69 static struct vnode *
   70                 umap_node_find __P((struct mount *mp, struct vnode *targetvp));
   71 
   72 /*
   73  * Initialise cache headers
   74  */
   75 int
   76 umapfs_init(vfsp)
   77         struct vfsconf *vfsp;
   78 {
   79 
   80 #ifdef UMAPFS_DIAGNOSTIC
   81         printf("umapfs_init\n");                /* printed during system boot */
   82 #endif
   83         umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
   84         return (0);
   85 }
   86 
   87 /*
   88  * umap_findid is called by various routines in umap_vnodeops.c to
   89  * find a user or group id in a map.
   90  */
   91 static u_long
   92 umap_findid(id, map, nentries)
   93         u_long id;
   94         u_long map[][2];
   95         int nentries;
   96 {
   97         int i;
   98 
   99         /* Find uid entry in map */
  100         i = 0;
  101         while ((i<nentries) && ((map[i][0]) != id))
  102                 i++;
  103 
  104         if (i < nentries)
  105                 return (map[i][1]);
  106         else
  107                 return (-1);
  108 
  109 }
  110 
  111 /*
  112  * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to
  113  * find a user or group id in a map, in reverse.
  114  */
  115 u_long
  116 umap_reverse_findid(id, map, nentries)
  117         u_long id;
  118         u_long map[][2];
  119         int nentries;
  120 {
  121         int i;
  122 
  123         /* Find uid entry in map */
  124         i = 0;
  125         while ((i<nentries) && ((map[i][1]) != id))
  126                 i++;
  127 
  128         if (i < nentries)
  129                 return (map[i][0]);
  130         else
  131                 return (-1);
  132 
  133 }
  134 
  135 /*
  136  * Return alias for target vnode if already exists, else 0.
  137  */
  138 static struct vnode *
  139 umap_node_find(mp, targetvp)
  140         struct mount *mp;
  141         struct vnode *targetvp;
  142 {
  143         struct proc *p = curproc;               /* XXX */
  144         struct umap_node_hashhead *hd;
  145         struct umap_node *a;
  146         struct vnode *vp;
  147 
  148 #ifdef UMAPFS_DIAGNOSTIC
  149         printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);
  150 #endif
  151 
  152         /*
  153          * Find hash base, and then search the (two-way) linked
  154          * list looking for a umap_node structure which is referencing
  155          * the target vnode.  If found, the increment the umap_node
  156          * reference count (but NOT the target vnode's VREF counter).
  157          */
  158         hd = UMAP_NHASH(targetvp);
  159 loop:
  160         for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
  161                 if (a->umap_lowervp == targetvp &&
  162                     a->umap_vnode->v_mount == mp) {
  163                         vp = UMAPTOV(a);
  164                         /*
  165                          * We need vget for the VXLOCK
  166                          * stuff, but we don't want to lock
  167                          * the lower node.
  168                          */
  169                         if (vget(vp, 0, p)) {
  170 #ifdef UMAPFS_DIAGNOSTIC
  171                                 printf ("umap_node_find: vget failed.\n");
  172 #endif
  173                                 goto loop;
  174                         }
  175                         return (vp);
  176                 }
  177         }
  178 
  179 #ifdef UMAPFS_DIAGNOSTIC
  180         printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp);
  181 #endif
  182 
  183         return (0);
  184 }
  185 
  186 /*
  187  * Make a new umap_node node.
  188  * Vp is the alias vnode, lofsvp is the target vnode.
  189  * Maintain a reference to (targetvp).
  190  */
  191 static int
  192 umap_node_alloc(mp, lowervp, vpp)
  193         struct mount *mp;
  194         struct vnode *lowervp;
  195         struct vnode **vpp;
  196 {
  197         struct umap_node_hashhead *hd;
  198         struct umap_node *xp;
  199         struct vnode *othervp, *vp;
  200         int error;
  201 
  202         /* XXX This routine probably needs a node_alloc lock */
  203 
  204         /*
  205          * Do the MALLOC before the getnewvnode since doing so afterward
  206          * might cause a bogus v_data pointer to get dereferenced
  207          * elsewhere if MALLOC should block.
  208          */
  209         MALLOC(xp, struct umap_node *, sizeof(struct umap_node),
  210             M_TEMP, M_WAITOK);
  211 
  212         error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, vpp);
  213         if (error) {
  214                 FREE(xp, M_TEMP);
  215                 return (error);
  216         }
  217         vp = *vpp;
  218 
  219         vp->v_type = lowervp->v_type;
  220         xp->umap_vnode = vp;
  221         vp->v_data = xp;
  222         xp->umap_lowervp = lowervp;
  223         /*
  224          * Before we insert our new node onto the hash chains,
  225          * check to see if someone else has beaten us to it.
  226          * (We could have slept in MALLOC.)
  227          */
  228         othervp = umap_node_find(mp, lowervp);
  229         if (othervp) {
  230                 FREE(xp, M_TEMP);
  231                 vp->v_type = VBAD;      /* node is discarded */
  232                 vp->v_usecount = 0;     /* XXX */
  233                 *vpp = othervp;
  234                 return (0);
  235         }
  236         VREF(lowervp);   /* Extra VREF will be vrele'd in umap_node_create */
  237         hd = UMAP_NHASH(lowervp);
  238         LIST_INSERT_HEAD(hd, xp, umap_hash);
  239         return (0);
  240 }
  241 
  242 
  243 /*
  244  * Try to find an existing umap_node vnode refering
  245  * to it, otherwise make a new umap_node vnode which
  246  * contains a reference to the target vnode.
  247  */
  248 int
  249 umap_node_create(mp, targetvp, newvpp)
  250         struct mount *mp;
  251         struct vnode *targetvp;
  252         struct vnode **newvpp;
  253 {
  254         struct vnode *aliasvp;
  255 
  256         aliasvp = umap_node_find(mp, targetvp);
  257         if (aliasvp) {
  258                 /*
  259                  * Take another reference to the alias vnode
  260                  */
  261 #ifdef UMAPFS_DIAGNOSTIC
  262                 vprint("umap_node_create: exists", aliasvp);
  263 #endif
  264                 /* VREF(aliasvp); */
  265         } else {
  266                 int error;
  267 
  268                 /*
  269                  * Get new vnode.
  270                  */
  271 #ifdef UMAPFS_DIAGNOSTIC
  272                 printf("umap_node_create: create new alias vnode\n");
  273 #endif
  274                 /*
  275                  * Make new vnode reference the umap_node.
  276                  */
  277                 error = umap_node_alloc(mp, targetvp, &aliasvp);
  278                 if (error)
  279                         return (error);
  280 
  281                 /*
  282                  * aliasvp is already VREF'd by getnewvnode()
  283                  */
  284         }
  285 
  286         vrele(targetvp);
  287 
  288 #ifdef UMAPFS_DIAGNOSTIC
  289         vprint("umap_node_create: alias", aliasvp);
  290         vprint("umap_node_create: target", targetvp);
  291 #endif
  292 
  293         *newvpp = aliasvp;
  294         return (0);
  295 }
  296 
  297 #ifdef UMAPFS_DIAGNOSTIC
  298 int umap_checkvp_barrier = 1;
  299 struct vnode *
  300 umap_checkvp(vp, fil, lno)
  301         struct vnode *vp;
  302         char *fil;
  303         int lno;
  304 {
  305         struct umap_node *a = VTOUMAP(vp);
  306 #if 0
  307         /*
  308          * Can't do this check because vop_reclaim runs
  309          * with funny vop vector.
  310          */
  311         if (vp->v_op != umap_vnodeop_p) {
  312                 printf ("umap_checkvp: on non-umap-node\n");
  313                 while (umap_checkvp_barrier) /*WAIT*/ ;
  314                 panic("umap_checkvp");
  315         }
  316 #endif
  317         if (a->umap_lowervp == NULL) {
  318                 /* Should never happen */
  319                 int i; u_long *p;
  320                 printf("vp = %x, ZERO ptr\n", vp);
  321                 for (p = (u_long *) a, i = 0; i < 8; i++)
  322                         printf(" %x", p[i]);
  323                 printf("\n");
  324                 /* wait for debugger */
  325                 while (umap_checkvp_barrier) /*WAIT*/ ;
  326                 panic("umap_checkvp");
  327         }
  328         if (a->umap_lowervp->v_usecount < 1) {
  329                 int i; u_long *p;
  330                 printf("vp = %x, unref'ed lowervp\n", vp);
  331                 for (p = (u_long *) a, i = 0; i < 8; i++)
  332                         printf(" %x", p[i]);
  333                 printf("\n");
  334                 /* wait for debugger */
  335                 while (umap_checkvp_barrier) /*WAIT*/ ;
  336                 panic ("umap with unref'ed lowervp");
  337         }
  338 #if 0
  339         printf("umap %x/%d -> %x/%d [%s, %d]\n",
  340                 a->umap_vnode, a->umap_vnode->v_usecount,
  341                 a->umap_lowervp, a->umap_lowervp->v_usecount,
  342                 fil, lno);
  343 #endif
  344         return (a->umap_lowervp);
  345 }
  346 #endif
  347 
  348 /* umap_mapids maps all of the ids in a credential, both user and group. */
  349 
  350 void
  351 umap_mapids(v_mount, credp)
  352         struct mount *v_mount;
  353         struct ucred *credp;
  354 {
  355         int i;
  356         uid_t uid;
  357         gid_t gid;
  358 
  359         if (credp == NOCRED)
  360                 return;
  361 
  362         /* Find uid entry in map */
  363 
  364         uid = (uid_t) umap_findid(credp->cr_uid,
  365                                 MOUNTTOUMAPMOUNT(v_mount)->info_mapdata,
  366                                 MOUNTTOUMAPMOUNT(v_mount)->info_nentries);
  367 
  368         if (uid != -1)
  369                 credp->cr_uid = uid;
  370         else
  371                 credp->cr_uid = (uid_t) NOBODY;
  372 
  373 #ifdef notdef
  374         /* cr_gid is the same as cr_groups[0] in 4BSD */
  375 
  376         /* Find gid entry in map */
  377 
  378         gid = (gid_t) umap_findid(credp->cr_gid,
  379                                 MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata,
  380                                 MOUNTTOUMAPMOUNT(v_mount)->info_gnentries);
  381 
  382         if (gid != -1)
  383                 credp->cr_gid = gid;
  384         else
  385                 credp->cr_gid = NULLGROUP;
  386 #endif
  387 
  388         /* Now we must map each of the set of groups in the cr_groups
  389                 structure. */
  390 
  391         i = 0;
  392         while (credp->cr_groups[i] != 0) {
  393                 gid = (gid_t) umap_findid(credp->cr_groups[i],
  394                                 MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata,
  395                                 MOUNTTOUMAPMOUNT(v_mount)->info_gnentries);
  396 
  397                 if (gid != -1)
  398                         credp->cr_groups[i++] = gid;
  399                 else
  400                         credp->cr_groups[i++] = NULLGROUP;
  401         }
  402 }

Cache object: 8b42dfdd75450a4d3381b60e6fdbd2bf


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