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_vnops.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
    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_vnops.c        8.6 (Berkeley) 5/22/95
   37  * $FreeBSD$
   38  */
   39 
   40 /*
   41  * Umap Layer
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/sysctl.h>
   48 #include <sys/vnode.h>
   49 #include <sys/mount.h>
   50 #include <sys/namei.h>
   51 #include <sys/malloc.h>
   52 #include <sys/buf.h>
   53 #include <miscfs/umapfs/umap.h>
   54 #include <miscfs/nullfs/null.h>
   55 
   56 static int umap_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */
   57 SYSCTL_INT(_debug, OID_AUTO, umapfs_bug_bypass, CTLFLAG_RW,
   58         &umap_bug_bypass, 0, "");
   59 
   60 static int      umap_bwrite __P((struct vop_bwrite_args *ap));
   61 static int      umap_bypass __P((struct vop_generic_args *ap));
   62 static int      umap_getattr __P((struct vop_getattr_args *ap));
   63 static int      umap_inactive __P((struct vop_inactive_args *ap));
   64 static int      umap_lock __P((struct vop_lock_args *ap));
   65 static int      umap_print __P((struct vop_print_args *ap));
   66 static int      umap_reclaim __P((struct vop_reclaim_args *ap));
   67 static int      umap_rename __P((struct vop_rename_args *ap));
   68 static int      umap_strategy __P((struct vop_strategy_args *ap));
   69 static int      umap_unlock __P((struct vop_unlock_args *ap));
   70 
   71 /*
   72  * This is the 10-Apr-92 bypass routine.
   73  * See null_vnops.c:null_bypass for more details.
   74  */
   75 static int
   76 umap_bypass(ap)
   77         struct vop_generic_args /* {
   78                 struct vnodeop_desc *a_desc;
   79                 <other random data follows, presumably>
   80         } */ *ap;
   81 {
   82         struct ucred **credpp = 0, *credp = 0;
   83         struct ucred *savecredp = 0, *savecompcredp = 0;
   84         struct ucred *compcredp = 0;
   85         struct vnode **this_vp_p;
   86         int error;
   87         struct vnode *old_vps[VDESC_MAX_VPS];
   88         struct vnode *vp1 = 0;
   89         struct vnode **vps_p[VDESC_MAX_VPS];
   90         struct vnode ***vppp;
   91         struct vnodeop_desc *descp = ap->a_desc;
   92         int reles, i;
   93         struct componentname **compnamepp = 0;
   94 
   95         if (umap_bug_bypass)
   96                 printf ("umap_bypass: %s\n", descp->vdesc_name);
   97 
   98 #ifdef SAFETY
   99         /*
  100          * We require at least one vp.
  101          */
  102         if (descp->vdesc_vp_offsets == NULL ||
  103             descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
  104                 panic ("umap_bypass: no vp's in map.");
  105 #endif
  106 
  107         /*
  108          * Map the vnodes going in.
  109          * Later, we'll invoke the operation based on
  110          * the first mapped vnode's operation vector.
  111          */
  112         reles = descp->vdesc_flags;
  113         for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
  114                 if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
  115                         break;   /* bail out at end of list */
  116                 vps_p[i] = this_vp_p =
  117                         VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap);
  118 
  119                 if (i == 0) {
  120                         vp1 = *vps_p[0];
  121                 }
  122 
  123                 /*
  124                  * We're not guaranteed that any but the first vnode
  125                  * are of our type.  Check for and don't map any
  126                  * that aren't.  (Must map first vp or vclean fails.)
  127                  */
  128 
  129                 if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
  130                         old_vps[i] = NULL;
  131                 } else {
  132                         old_vps[i] = *this_vp_p;
  133                         *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
  134                         if (reles & 1)
  135                                 VREF(*this_vp_p);
  136                 }
  137 
  138         }
  139 
  140         /*
  141          * Fix the credentials.  (That's the purpose of this layer.)
  142          */
  143 
  144         if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
  145 
  146                 credpp = VOPARG_OFFSETTO(struct ucred**,
  147                     descp->vdesc_cred_offset, ap);
  148 
  149                 /* Save old values */
  150 
  151                 savecredp = (*credpp);
  152                 if (savecredp != NOCRED)
  153                         (*credpp) = crdup(savecredp);
  154                 credp = *credpp;
  155 
  156                 if (umap_bug_bypass && credp->cr_uid != 0)
  157                         printf("umap_bypass: user was %lu, group %lu\n",
  158                             (u_long)credp->cr_uid, (u_long)credp->cr_gid);
  159 
  160                 /* Map all ids in the credential structure. */
  161 
  162                 umap_mapids(vp1->v_mount, credp);
  163 
  164                 if (umap_bug_bypass && credp->cr_uid != 0)
  165                         printf("umap_bypass: user now %lu, group %lu\n",
  166                             (u_long)credp->cr_uid, (u_long)credp->cr_gid);
  167         }
  168 
  169         /* BSD often keeps a credential in the componentname structure
  170          * for speed.  If there is one, it better get mapped, too.
  171          */
  172 
  173         if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
  174 
  175                 compnamepp = VOPARG_OFFSETTO(struct componentname**,
  176                     descp->vdesc_componentname_offset, ap);
  177 
  178                 compcredp = (*compnamepp)->cn_cred;
  179                 savecompcredp = compcredp;
  180                 if (savecompcredp != NOCRED)
  181                         (*compnamepp)->cn_cred = crdup(savecompcredp);
  182                 compcredp = (*compnamepp)->cn_cred;
  183 
  184                 if (umap_bug_bypass && compcredp->cr_uid != 0)
  185                         printf(
  186                     "umap_bypass: component credit user was %lu, group %lu\n",
  187                             (u_long)compcredp->cr_uid,
  188                             (u_long)compcredp->cr_gid);
  189 
  190                 /* Map all ids in the credential structure. */
  191 
  192                 umap_mapids(vp1->v_mount, compcredp);
  193 
  194                 if (umap_bug_bypass && compcredp->cr_uid != 0)
  195                         printf(
  196                     "umap_bypass: component credit user now %lu, group %lu\n",
  197                             (u_long)compcredp->cr_uid,
  198                             (u_long)compcredp->cr_gid);
  199         }
  200 
  201         /*
  202          * Call the operation on the lower layer
  203          * with the modified argument structure.
  204          */
  205         error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
  206 
  207         /*
  208          * Maintain the illusion of call-by-value
  209          * by restoring vnodes in the argument structure
  210          * to their original value.
  211          */
  212         reles = descp->vdesc_flags;
  213         for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
  214                 if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
  215                         break;   /* bail out at end of list */
  216                 if (old_vps[i]) {
  217                         *(vps_p[i]) = old_vps[i];
  218                         if (reles & 1)
  219                                 vrele(*(vps_p[i]));
  220                 };
  221         };
  222 
  223         /*
  224          * Map the possible out-going vpp
  225          * (Assumes that the lower layer always returns
  226          * a VREF'ed vpp unless it gets an error.)
  227          */
  228         if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
  229             !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
  230             !error) {
  231                 if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
  232                         goto out;
  233                 vppp = VOPARG_OFFSETTO(struct vnode***,
  234                                  descp->vdesc_vpp_offset, ap);
  235                 if (*vppp)
  236                         error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
  237         };
  238 
  239  out:
  240         /*
  241          * Free duplicate cred structure and restore old one.
  242          */
  243         if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
  244                 if (umap_bug_bypass && credp && credp->cr_uid != 0)
  245                         printf("umap_bypass: returning-user was %lu\n",
  246                             (u_long)credp->cr_uid);
  247 
  248                 if (savecredp != NOCRED) {
  249                         crfree(credp);
  250                         (*credpp) = savecredp;
  251                         if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
  252                                 printf(
  253                                     "umap_bypass: returning-user now %lu\n\n",
  254                                     (u_long)(*credpp)->cr_uid);
  255                 }
  256         }
  257 
  258         if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
  259                 if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0)
  260                         printf(
  261                             "umap_bypass: returning-component-user was %lu\n",
  262                             (u_long)compcredp->cr_uid);
  263 
  264                 if (savecompcredp != NOCRED) {
  265                         crfree(compcredp);
  266                         (*compnamepp)->cn_cred = savecompcredp;
  267                         if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0)
  268                                 printf(
  269                             "umap_bypass: returning-component-user now %lu\n",
  270                                     (u_long)compcredp->cr_uid);
  271                 }
  272         }
  273 
  274         return (error);
  275 }
  276 
  277 
  278 /*
  279  *  We handle getattr to change the fsid.
  280  */
  281 static int
  282 umap_getattr(ap)
  283         struct vop_getattr_args /* {
  284                 struct vnode *a_vp;
  285                 struct vattr *a_vap;
  286                 struct ucred *a_cred;
  287                 struct proc *a_p;
  288         } */ *ap;
  289 {
  290         short uid, gid;
  291         int error, tmpid, nentries, gnentries;
  292         u_long (*mapdata)[2], (*gmapdata)[2];
  293         struct vnode **vp1p;
  294         struct vnodeop_desc *descp = ap->a_desc;
  295 
  296         error = umap_bypass((struct vop_generic_args *)ap);
  297         if (error)
  298                 return (error);
  299         /* Requires that arguments be restored. */
  300         ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
  301 
  302         /*
  303          * Umap needs to map the uid and gid returned by a stat
  304          * into the proper values for this site.  This involves
  305          * finding the returned uid in the mapping information,
  306          * translating it into the uid on the other end,
  307          * and filling in the proper field in the vattr
  308          * structure pointed to by ap->a_vap.  The group
  309          * is easier, since currently all groups will be
  310          * translate to the NULLGROUP.
  311          */
  312 
  313         /* Find entry in map */
  314 
  315         uid = ap->a_vap->va_uid;
  316         gid = ap->a_vap->va_gid;
  317         if (umap_bug_bypass)
  318                 printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid,
  319                     gid);
  320 
  321         vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap);
  322         nentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries;
  323         mapdata =  (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata);
  324         gnentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries;
  325         gmapdata =  (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata);
  326 
  327         /* Reverse map the uid for the vnode.  Since it's a reverse
  328                 map, we can't use umap_mapids() to do it. */
  329 
  330         tmpid = umap_reverse_findid(uid, mapdata, nentries);
  331 
  332         if (tmpid != -1) {
  333 
  334                 ap->a_vap->va_uid = (uid_t) tmpid;
  335                 if (umap_bug_bypass)
  336                         printf("umap_getattr: original uid = %d\n", uid);
  337         } else
  338                 ap->a_vap->va_uid = (uid_t) NOBODY;
  339 
  340         /* Reverse map the gid for the vnode. */
  341 
  342         tmpid = umap_reverse_findid(gid, gmapdata, gnentries);
  343 
  344         if (tmpid != -1) {
  345 
  346                 ap->a_vap->va_gid = (gid_t) tmpid;
  347                 if (umap_bug_bypass)
  348                         printf("umap_getattr: original gid = %d\n", gid);
  349         } else
  350                 ap->a_vap->va_gid = (gid_t) NULLGROUP;
  351 
  352         return (0);
  353 }
  354 
  355 /*
  356  * We need to process our own vnode lock and then clear the
  357  * interlock flag as it applies only to our vnode, not the
  358  * vnodes below us on the stack.
  359  */
  360 static int
  361 umap_lock(ap)
  362         struct vop_lock_args /* {
  363                 struct vnode *a_vp;
  364                 int a_flags;
  365                 struct proc *a_p;
  366         } */ *ap;
  367 {
  368 
  369         vop_nolock(ap);
  370         if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
  371                 return (0);
  372         ap->a_flags &= ~LK_INTERLOCK;
  373         return (null_bypass((struct vop_generic_args *)ap));
  374 }
  375 
  376 /*
  377  * We need to process our own vnode unlock and then clear the
  378  * interlock flag as it applies only to our vnode, not the
  379  * vnodes below us on the stack.
  380  */
  381 int
  382 umap_unlock(ap)
  383         struct vop_unlock_args /* {
  384                 struct vnode *a_vp;
  385                 int a_flags;
  386                 struct proc *a_p;
  387         } */ *ap;
  388 {
  389         vop_nounlock(ap);
  390         ap->a_flags &= ~LK_INTERLOCK;
  391         return (null_bypass((struct vop_generic_args *)ap));
  392 }
  393 
  394 static int
  395 umap_inactive(ap)
  396         struct vop_inactive_args /* {
  397                 struct vnode *a_vp;
  398                 struct proc *a_p;
  399         } */ *ap;
  400 {
  401         struct vnode *vp = ap->a_vp;
  402         struct umap_node *xp = VTOUMAP(vp);
  403         struct vnode *lowervp = xp->umap_lowervp;
  404         /*
  405          * Do nothing (and _don't_ bypass).
  406          * Wait to vrele lowervp until reclaim,
  407          * so that until then our umap_node is in the
  408          * cache and reusable.
  409          *
  410          */
  411         VOP_INACTIVE(lowervp, ap->a_p);
  412         VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
  413         return (0);
  414 }
  415 
  416 static int
  417 umap_reclaim(ap)
  418         struct vop_reclaim_args /* {
  419                 struct vnode *a_vp;
  420         } */ *ap;
  421 {
  422         struct vnode *vp = ap->a_vp;
  423         struct umap_node *xp = VTOUMAP(vp);
  424         struct vnode *lowervp = xp->umap_lowervp;
  425 
  426         /* After this assignment, this node will not be re-used. */
  427         xp->umap_lowervp = NULL;
  428         LIST_REMOVE(xp, umap_hash);
  429         FREE(vp->v_data, M_TEMP);
  430         vp->v_data = NULL;
  431         vrele(lowervp);
  432         return (0);
  433 }
  434 
  435 static int
  436 umap_strategy(ap)
  437         struct vop_strategy_args /* {
  438                 struct vnode *a_vp;
  439                 struct buf *a_bp;
  440         } */ *ap;
  441 {
  442         struct buf *bp = ap->a_bp;
  443         int error;
  444         struct vnode *savedvp;
  445 
  446         savedvp = bp->b_vp;
  447         bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
  448 
  449         error = VOP_STRATEGY(bp->b_vp, ap->a_bp);
  450 
  451         bp->b_vp = savedvp;
  452 
  453         return (error);
  454 }
  455 
  456 static int
  457 umap_bwrite(ap)
  458         struct vop_bwrite_args /* {
  459                 struct buf *a_bp;
  460         } */ *ap;
  461 {
  462         struct buf *bp = ap->a_bp;
  463         int error;
  464         struct vnode *savedvp;
  465 
  466         savedvp = bp->b_vp;
  467         bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
  468 
  469         error = VOP_BWRITE(ap->a_bp);
  470 
  471         bp->b_vp = savedvp;
  472 
  473         return (error);
  474 }
  475 
  476 
  477 static int
  478 umap_print(ap)
  479         struct vop_print_args /* {
  480                 struct vnode *a_vp;
  481         } */ *ap;
  482 {
  483         struct vnode *vp = ap->a_vp;
  484         printf("\ttag VT_UMAPFS, vp=%p, lowervp=%p\n", vp, UMAPVPTOLOWERVP(vp));
  485         return (0);
  486 }
  487 
  488 static int
  489 umap_rename(ap)
  490         struct vop_rename_args  /* {
  491                 struct vnode *a_fdvp;
  492                 struct vnode *a_fvp;
  493                 struct componentname *a_fcnp;
  494                 struct vnode *a_tdvp;
  495                 struct vnode *a_tvp;
  496                 struct componentname *a_tcnp;
  497         } */ *ap;
  498 {
  499         int error;
  500         struct componentname *compnamep;
  501         struct ucred *compcredp, *savecompcredp;
  502         struct vnode *vp;
  503 
  504         /*
  505          * Rename is irregular, having two componentname structures.
  506          * We need to map the cre in the second structure,
  507          * and then bypass takes care of the rest.
  508          */
  509 
  510         vp = ap->a_fdvp;
  511         compnamep = ap->a_tcnp;
  512         compcredp = compnamep->cn_cred;
  513 
  514         savecompcredp = compcredp;
  515         compcredp = compnamep->cn_cred = crdup(savecompcredp);
  516 
  517         if (umap_bug_bypass && compcredp->cr_uid != 0)
  518                 printf(
  519             "umap_rename: rename component credit user was %lu, group %lu\n",
  520                     (u_long)compcredp->cr_uid, (u_long)compcredp->cr_gid);
  521 
  522         /* Map all ids in the credential structure. */
  523 
  524         umap_mapids(vp->v_mount, compcredp);
  525 
  526         if (umap_bug_bypass && compcredp->cr_uid != 0)
  527                 printf(
  528             "umap_rename: rename component credit user now %lu, group %lu\n",
  529                     (u_long)compcredp->cr_uid, (u_long)compcredp->cr_gid);
  530 
  531         error = umap_bypass((struct vop_generic_args *)ap);
  532 
  533         /* Restore the additional mapped componentname cred structure. */
  534 
  535         crfree(compcredp);
  536         compnamep->cn_cred = savecompcredp;
  537 
  538         return error;
  539 }
  540 
  541 /*
  542  * Global vfs data structures
  543  */
  544 /*
  545  * XXX - strategy, bwrite are hand coded currently.  They should
  546  * go away with a merged buffer/block cache.
  547  *
  548  */
  549 vop_t **umap_vnodeop_p;
  550 static struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
  551         { &vop_default_desc,            (vop_t *) umap_bypass },
  552         { &vop_bwrite_desc,             (vop_t *) umap_bwrite },
  553         { &vop_getattr_desc,            (vop_t *) umap_getattr },
  554         { &vop_inactive_desc,           (vop_t *) umap_inactive },
  555         { &vop_lock_desc,               (vop_t *) umap_lock },
  556         { &vop_print_desc,              (vop_t *) umap_print },
  557         { &vop_reclaim_desc,            (vop_t *) umap_reclaim },
  558         { &vop_rename_desc,             (vop_t *) umap_rename },
  559         { &vop_strategy_desc,           (vop_t *) umap_strategy },
  560         { &vop_unlock_desc,             (vop_t *) umap_unlock },
  561         { NULL, NULL }
  562 };
  563 static struct vnodeopv_desc umap_vnodeop_opv_desc =
  564         { &umap_vnodeop_p, umap_vnodeop_entries };
  565 
  566 VNODEOP_SET(umap_vnodeop_opv_desc);

Cache object: 67d99481ddddc2c8581c9895eb33d7be


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