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

Cache object: d489794c7821e8b95dc3d2ffc211dc14


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