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/union/union_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 /*      $NetBSD: union_vfsops.c,v 1.11.2.2 2006/01/06 23:53:37 riz Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1994 The Regents of the University of California.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software donated to Berkeley by
    8  * Jan-Simon Pendry.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)union_vfsops.c      8.20 (Berkeley) 5/20/95
   35  */
   36 
   37 /*
   38  * Copyright (c) 1994 Jan-Simon Pendry.
   39  * All rights reserved.
   40  *
   41  * This code is derived from software donated to Berkeley by
   42  * Jan-Simon Pendry.
   43  *
   44  * Redistribution and use in source and binary forms, with or without
   45  * modification, are permitted provided that the following conditions
   46  * are met:
   47  * 1. Redistributions of source code must retain the above copyright
   48  *    notice, this list of conditions and the following disclaimer.
   49  * 2. Redistributions in binary form must reproduce the above copyright
   50  *    notice, this list of conditions and the following disclaimer in the
   51  *    documentation and/or other materials provided with the distribution.
   52  * 3. All advertising materials mentioning features or use of this software
   53  *    must display the following acknowledgement:
   54  *      This product includes software developed by the University of
   55  *      California, Berkeley and its contributors.
   56  * 4. Neither the name of the University nor the names of its contributors
   57  *    may be used to endorse or promote products derived from this software
   58  *    without specific prior written permission.
   59  *
   60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   70  * SUCH DAMAGE.
   71  *
   72  *      @(#)union_vfsops.c      8.20 (Berkeley) 5/20/95
   73  */
   74 
   75 /*
   76  * Union Layer
   77  */
   78 
   79 #include <sys/cdefs.h>
   80 __KERNEL_RCSID(0, "$NetBSD: union_vfsops.c,v 1.11.2.2 2006/01/06 23:53:37 riz Exp $");
   81 
   82 #include <sys/param.h>
   83 #include <sys/systm.h>
   84 #include <sys/sysctl.h>
   85 #include <sys/time.h>
   86 #include <sys/proc.h>
   87 #include <sys/vnode.h>
   88 #include <sys/mount.h>
   89 #include <sys/namei.h>
   90 #include <sys/malloc.h>
   91 #include <sys/filedesc.h>
   92 #include <sys/queue.h>
   93 #include <sys/stat.h>
   94 
   95 #include <fs/union/union.h>
   96 
   97 int union_mount __P((struct mount *, const char *, void *, struct nameidata *,
   98                      struct proc *));
   99 int union_start __P((struct mount *, int, struct proc *));
  100 int union_unmount __P((struct mount *, int, struct proc *));
  101 int union_root __P((struct mount *, struct vnode **));
  102 int union_quotactl __P((struct mount *, int, uid_t, caddr_t, struct proc *));
  103 int union_statfs __P((struct mount *, struct statfs *, struct proc *));
  104 int union_sync __P((struct mount *, int, struct ucred *, struct proc *));
  105 int union_vget __P((struct mount *, ino_t, struct vnode **));
  106 int union_fhtovp __P((struct mount *, struct fid *, struct vnode **));
  107 int union_checkexp __P((struct mount *, struct mbuf *, int *,
  108                       struct ucred **));
  109 int union_vptofh __P((struct vnode *, struct fid *));
  110 
  111 /*
  112  * Mount union filesystem
  113  */
  114 int
  115 union_mount(mp, path, data, ndp, p)
  116         struct mount *mp;
  117         const char *path;
  118         void *data;
  119         struct nameidata *ndp;
  120         struct proc *p;
  121 {
  122         int error = 0;
  123         struct union_args args;
  124         struct vnode *lowerrootvp = NULLVP;
  125         struct vnode *upperrootvp = NULLVP;
  126         struct union_mount *um = 0;
  127         struct ucred *cred = 0;
  128         char *cp;
  129         int len;
  130         size_t size;
  131 
  132 #ifdef UNION_DIAGNOSTIC
  133         printf("union_mount(mp = %p)\n", mp);
  134 #endif
  135 
  136         if (mp->mnt_flag & MNT_GETARGS) {
  137                 um = MOUNTTOUNIONMOUNT(mp);
  138                 if (um == NULL)
  139                         return EIO;
  140                 args.target = NULL;
  141                 args.mntflags = um->um_op;
  142                 return copyout(&args, data, sizeof(args));
  143         }
  144         /*
  145          * Update is a no-op
  146          */
  147         if (mp->mnt_flag & MNT_UPDATE) {
  148                 /*
  149                  * Need to provide.
  150                  * 1. a way to convert between rdonly and rdwr mounts.
  151                  * 2. support for nfs exports.
  152                  */
  153                 error = EOPNOTSUPP;
  154                 goto bad;
  155         }
  156 
  157         /*
  158          * Get argument
  159          */
  160         error = copyin(data, (caddr_t)&args, sizeof(struct union_args));
  161         if (error)
  162                 goto bad;
  163 
  164         lowerrootvp = mp->mnt_vnodecovered;
  165         VREF(lowerrootvp);
  166 
  167         /*
  168          * Find upper node.
  169          */
  170         NDINIT(ndp, LOOKUP, FOLLOW,
  171                UIO_USERSPACE, args.target, p);
  172 
  173         if ((error = namei(ndp)) != 0)
  174                 goto bad;
  175 
  176         upperrootvp = ndp->ni_vp;
  177 
  178         if (upperrootvp->v_type != VDIR) {
  179                 error = EINVAL;
  180                 goto bad;
  181         }
  182         
  183         um = (struct union_mount *) malloc(sizeof(struct union_mount),
  184                                 M_UFSMNT, M_WAITOK);    /* XXX */
  185 
  186         /*
  187          * Keep a held reference to the target vnodes.
  188          * They are vrele'd in union_unmount.
  189          *
  190          * Depending on the _BELOW flag, the filesystems are
  191          * viewed in a different order.  In effect, this is the
  192          * same as providing a mount under option to the mount syscall.
  193          */
  194 
  195         um->um_op = args.mntflags & UNMNT_OPMASK;
  196         switch (um->um_op) {
  197         case UNMNT_ABOVE:
  198                 um->um_lowervp = lowerrootvp;
  199                 um->um_uppervp = upperrootvp;
  200                 break;
  201 
  202         case UNMNT_BELOW:
  203                 um->um_lowervp = upperrootvp;
  204                 um->um_uppervp = lowerrootvp;
  205                 break;
  206 
  207         case UNMNT_REPLACE:
  208                 vrele(lowerrootvp);
  209                 lowerrootvp = NULLVP;
  210                 um->um_uppervp = upperrootvp;
  211                 um->um_lowervp = lowerrootvp;
  212                 break;
  213 
  214         default:
  215                 error = EINVAL;
  216                 goto bad;
  217         }
  218 
  219         /*
  220          * Unless the mount is readonly, ensure that the top layer
  221          * supports whiteout operations
  222          */
  223         if ((mp->mnt_flag & MNT_RDONLY) == 0) {
  224                 error = VOP_WHITEOUT(um->um_uppervp, (struct componentname *) 0, LOOKUP);
  225                 if (error)
  226                         goto bad;
  227         }
  228 
  229         um->um_cred = p->p_ucred;
  230         crhold(um->um_cred);
  231         um->um_cmode = UN_DIRMODE &~ p->p_cwdi->cwdi_cmask;
  232 
  233         /*
  234          * Depending on what you think the MNT_LOCAL flag might mean,
  235          * you may want the && to be || on the conditional below.
  236          * At the moment it has been defined that the filesystem is
  237          * only local if it is all local, ie the MNT_LOCAL flag implies
  238          * that the entire namespace is local.  If you think the MNT_LOCAL
  239          * flag implies that some of the files might be stored locally
  240          * then you will want to change the conditional.
  241          */
  242         if (um->um_op == UNMNT_ABOVE) {
  243                 if (((um->um_lowervp == NULLVP) ||
  244                      (um->um_lowervp->v_mount->mnt_flag & MNT_LOCAL)) &&
  245                     (um->um_uppervp->v_mount->mnt_flag & MNT_LOCAL))
  246                         mp->mnt_flag |= MNT_LOCAL;
  247         }
  248 
  249         /*
  250          * Copy in the upper layer's RDONLY flag.  This is for the benefit
  251          * of lookup() which explicitly checks the flag, rather than asking
  252          * the filesystem for it's own opinion.  This means, that an update
  253          * mount of the underlying filesystem to go from rdonly to rdwr
  254          * will leave the unioned view as read-only.
  255          */
  256         mp->mnt_flag |= (um->um_uppervp->v_mount->mnt_flag & MNT_RDONLY);
  257 
  258         mp->mnt_data = um;
  259         vfs_getnewfsid(mp);
  260 
  261         error = set_statfs_info( path, UIO_USERSPACE, NULL, UIO_USERSPACE,
  262             mp, p);
  263         if (error)
  264                 goto bad;
  265 
  266         switch (um->um_op) {
  267         case UNMNT_ABOVE:
  268                 cp = "<above>:";
  269                 break;
  270         case UNMNT_BELOW:
  271                 cp = "<below>:";
  272                 break;
  273         case UNMNT_REPLACE:
  274                 cp = "";
  275                 break;
  276         default:
  277                 cp = "<invalid>:";
  278 #ifdef DIAGNOSTIC
  279                 panic("union_mount: bad um_op");
  280 #endif
  281                 break;
  282         }
  283         len = strlen(cp);
  284         memcpy(mp->mnt_stat.f_mntfromname, cp, len);
  285 
  286         cp = mp->mnt_stat.f_mntfromname + len;
  287         len = MNAMELEN - len;
  288 
  289         (void) copyinstr(args.target, cp, len - 1, &size);
  290         memset(cp + size, 0, len - size);
  291 
  292 #ifdef UNION_DIAGNOSTIC
  293         printf("union_mount: from %s, on %s\n",
  294             mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
  295 #endif
  296 
  297         /* Setup the readdir hook if it's not set already */
  298         if (!vn_union_readdir_hook)
  299                 vn_union_readdir_hook = union_readdirhook;
  300 
  301         return (0);
  302 
  303 bad:
  304         if (um)
  305                 free(um, M_UFSMNT);
  306         if (cred)
  307                 crfree(cred);
  308         if (upperrootvp)
  309                 vrele(upperrootvp);
  310         if (lowerrootvp)
  311                 vrele(lowerrootvp);
  312         return (error);
  313 }
  314 
  315 /*
  316  * VFS start.  Nothing needed here - the start routine
  317  * on the underlying filesystem(s) will have been called
  318  * when that filesystem was mounted.
  319  */
  320  /*ARGSUSED*/
  321 int
  322 union_start(mp, flags, p)
  323         struct mount *mp;
  324         int flags;
  325         struct proc *p;
  326 {
  327 
  328         return (0);
  329 }
  330 
  331 /*
  332  * Free reference to union layer
  333  */
  334 int
  335 union_unmount(mp, mntflags, p)
  336         struct mount *mp;
  337         int mntflags;
  338         struct proc *p;
  339 {
  340         struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
  341         int freeing;
  342 
  343 #ifdef UNION_DIAGNOSTIC
  344         printf("union_unmount(mp = %p)\n", mp);
  345 #endif
  346 
  347         /*
  348          * Keep flushing vnodes from the mount list.
  349          * This is needed because of the un_pvp held
  350          * reference to the parent vnode.
  351          * If more vnodes have been freed on a given pass,
  352          * the try again.  The loop will iterate at most
  353          * (d) times, where (d) is the maximum tree depth
  354          * in the filesystem.
  355          */
  356         for (freeing = 0; vflush(mp, NULL, 0) != 0;) {
  357                 struct vnode *vp;
  358                 int n;
  359 
  360                 /* count #vnodes held on mount list */
  361                 for (n = 0, vp = mp->mnt_vnodelist.lh_first;
  362                                 vp != NULLVP;
  363                                 vp = vp->v_mntvnodes.le_next)
  364                         n++;
  365 
  366                 /* if this is unchanged then stop */
  367                 if (n == freeing)
  368                         break;
  369 
  370                 /* otherwise try once more time */
  371                 freeing = n;
  372         }
  373 
  374         /*
  375          * Ok, now that we've tried doing it gently, get out the hammer.
  376          */
  377 
  378         if (mntflags & MNT_FORCE)
  379                 vflush(mp, NULL, FORCECLOSE);
  380 
  381 
  382         /*
  383          * Discard references to upper and lower target vnodes.
  384          */
  385         if (um->um_lowervp)
  386                 vrele(um->um_lowervp);
  387         vrele(um->um_uppervp);
  388         crfree(um->um_cred);
  389         /*
  390          * Finally, throw away the union_mount structure
  391          */
  392         free(mp->mnt_data, M_UFSMNT);   /* XXX */
  393         mp->mnt_data = 0;
  394         return (0);
  395 }
  396 
  397 int
  398 union_root(mp, vpp)
  399         struct mount *mp;
  400         struct vnode **vpp;
  401 {
  402         struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
  403         int error;
  404         int loselock;
  405 
  406         /*
  407          * Return locked reference to root.
  408          */
  409         VREF(um->um_uppervp);
  410         if ((um->um_op == UNMNT_BELOW) &&
  411              VOP_ISLOCKED(um->um_uppervp)) {
  412                 loselock = 1;
  413         } else {
  414                 vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY);
  415                 loselock = 0;
  416         }
  417         if (um->um_lowervp)
  418                 VREF(um->um_lowervp);
  419         error = union_allocvp(vpp, mp,
  420                               (struct vnode *) 0,
  421                               (struct vnode *) 0,
  422                               (struct componentname *) 0,
  423                               um->um_uppervp,
  424                               um->um_lowervp,
  425                               1);
  426 
  427         if (error) {
  428                 if (!loselock)
  429                         VOP_UNLOCK(um->um_uppervp, 0);
  430                 vrele(um->um_uppervp);
  431                 if (um->um_lowervp)
  432                         vrele(um->um_lowervp);
  433         } else {
  434                 if (loselock)
  435                         VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
  436         }
  437 
  438         return (error);
  439 }
  440 
  441 /*ARGSUSED*/
  442 int
  443 union_quotactl(mp, cmd, uid, arg, p)
  444         struct mount *mp;
  445         int cmd;
  446         uid_t uid;
  447         caddr_t arg;
  448         struct proc *p;
  449 {
  450 
  451         return (EOPNOTSUPP);
  452 }
  453 
  454 int
  455 union_statfs(mp, sbp, p)
  456         struct mount *mp;
  457         struct statfs *sbp;
  458         struct proc *p;
  459 {
  460         int error;
  461         struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
  462         struct statfs mstat;
  463         int lbsize;
  464 
  465 #ifdef UNION_DIAGNOSTIC
  466         printf("union_statfs(mp = %p, lvp = %p, uvp = %p)\n", mp,
  467             um->um_lowervp, um->um_uppervp);
  468 #endif
  469 
  470         memset(&mstat, 0, sizeof(mstat));
  471 
  472         if (um->um_lowervp) {
  473                 error = VFS_STATFS(um->um_lowervp->v_mount, &mstat, p);
  474                 if (error)
  475                         return (error);
  476         }
  477 
  478         /* now copy across the "interesting" information and fake the rest */
  479         lbsize = mstat.f_bsize;
  480         sbp->f_blocks = mstat.f_blocks - mstat.f_bfree;
  481         sbp->f_files = mstat.f_files - mstat.f_ffree;
  482 
  483         error = VFS_STATFS(um->um_uppervp->v_mount, &mstat, p);
  484         if (error)
  485                 return (error);
  486 
  487         sbp->f_type = 0;
  488         sbp->f_flags = mstat.f_flags;
  489         sbp->f_bsize = mstat.f_bsize;
  490         sbp->f_iosize = mstat.f_iosize;
  491 
  492         /*
  493          * The "total" fields count total resources in all layers,
  494          * the "free" fields count only those resources which are
  495          * free in the upper layer (since only the upper layer
  496          * is writable).
  497          */
  498 
  499         if (mstat.f_bsize != lbsize)
  500                 sbp->f_blocks = sbp->f_blocks * lbsize / mstat.f_bsize;
  501         sbp->f_blocks += mstat.f_blocks;
  502         sbp->f_bfree = mstat.f_bfree;
  503         sbp->f_bavail = mstat.f_bavail;
  504         sbp->f_files += mstat.f_files;
  505         sbp->f_ffree = mstat.f_ffree;
  506 
  507         copy_statfs_info(sbp, mp);
  508         return (0);
  509 }
  510 
  511 /*ARGSUSED*/
  512 int
  513 union_sync(mp, waitfor, cred, p)
  514         struct mount *mp;
  515         int waitfor;
  516         struct ucred *cred;
  517         struct proc *p;
  518 {
  519 
  520         /*
  521          * XXX - Assumes no data cached at union layer.
  522          */
  523         return (0);
  524 }
  525 
  526 /*ARGSUSED*/
  527 int
  528 union_vget(mp, ino, vpp)
  529         struct mount *mp;
  530         ino_t ino;
  531         struct vnode **vpp;
  532 {
  533         
  534         return (EOPNOTSUPP);
  535 }
  536 
  537 /*ARGSUSED*/
  538 int
  539 union_fhtovp(mp, fidp, vpp)
  540         struct mount *mp;
  541         struct fid *fidp;
  542         struct vnode **vpp;
  543 {
  544 
  545         return (EOPNOTSUPP);
  546 }
  547 
  548 /*ARGSUSED*/
  549 int
  550 union_checkexp(mp, nam, exflagsp, credanonp)
  551         struct mount *mp;
  552         struct mbuf *nam;
  553         int *exflagsp;
  554         struct ucred **credanonp;
  555 {
  556 
  557         return (EOPNOTSUPP);
  558 }
  559 
  560 /*ARGSUSED*/
  561 int
  562 union_vptofh(vp, fhp)
  563         struct vnode *vp;
  564         struct fid *fhp;
  565 {
  566 
  567         return (EOPNOTSUPP);
  568 }
  569 
  570 SYSCTL_SETUP(sysctl_vfs_union_setup, "sysctl vfs.union subtree setup")
  571 {
  572 
  573         sysctl_createv(clog, 0, NULL, NULL,
  574                        CTLFLAG_PERMANENT,
  575                        CTLTYPE_NODE, "vfs", NULL,
  576                        NULL, 0, NULL, 0,
  577                        CTL_VFS, CTL_EOL);
  578         sysctl_createv(clog, 0, NULL, NULL,
  579                        CTLFLAG_PERMANENT,
  580                        CTLTYPE_NODE, "union",
  581                        SYSCTL_DESCR("Union file system"),
  582                        NULL, 0, NULL, 0,
  583                        CTL_VFS, 15, CTL_EOL);
  584         /*
  585          * XXX the "15" above could be dynamic, thereby eliminating
  586          * one more instance of the "number to vfs" mapping problem,
  587          * but "15" is the order as taken from sys/mount.h
  588          */
  589 }
  590 
  591 extern const struct vnodeopv_desc union_vnodeop_opv_desc;
  592 
  593 const struct vnodeopv_desc * const union_vnodeopv_descs[] = {
  594         &union_vnodeop_opv_desc,
  595         NULL,
  596 };
  597 
  598 struct vfsops union_vfsops = {
  599         MOUNT_UNION,
  600         union_mount,
  601         union_start,
  602         union_unmount,
  603         union_root,
  604         union_quotactl,
  605         union_statfs,
  606         union_sync,
  607         union_vget,
  608         union_fhtovp,
  609         union_vptofh,
  610         union_init,
  611         NULL,                           /* vfs_reinit */
  612         union_done,
  613         NULL,
  614         NULL,                           /* vfs_mountroot */
  615         union_checkexp,
  616         union_vnodeopv_descs,
  617 };

Cache object: ec7e8957ee8edf0ef5c6ec2a5d9fb292


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