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/kern/vfs_default.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) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed
    6  * to Berkeley by John Heidemann of the UCLA Ficus project.
    7  *
    8  * The statvfs->statfs conversion code was contributed to the DragonFly
    9  * Project by Joerg Sonnenberger <joerg@bec.de>.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
   36  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/buf.h>
   42 #include <sys/conf.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/file.h>
   45 #include <sys/kernel.h>
   46 #include <sys/lock.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mount.h>
   49 #include <sys/unistd.h>
   50 #include <sys/vnode.h>
   51 #include <sys/namei.h>
   52 #include <sys/nlookup.h>
   53 #include <sys/mountctl.h>
   54 #include <sys/vfs_quota.h>
   55 
   56 #include <machine/limits.h>
   57 
   58 #include <vm/vm.h>
   59 #include <vm/vm_object.h>
   60 #include <vm/vm_page.h>
   61 #include <vm/vm_pager.h>
   62 #include <vm/vnode_pager.h>
   63 
   64 static int      vop_nolookup (struct vop_old_lookup_args *);
   65 static int      vop_nostrategy (struct vop_strategy_args *);
   66 
   67 /*
   68  * This vnode table stores what we want to do if the filesystem doesn't
   69  * implement a particular VOP.
   70  *
   71  * If there is no specific entry here, we will return EOPNOTSUPP.
   72  */
   73 struct vop_ops default_vnode_vops = {
   74         .vop_default            = vop_eopnotsupp,
   75         .vop_advlock            = (void *)vop_einval,
   76         .vop_fsync              = (void *)vop_null,
   77         .vop_ioctl              = (void *)vop_enotty,
   78         .vop_mmap               = (void *)vop_einval,
   79         .vop_old_lookup         = vop_nolookup,
   80         .vop_open               = vop_stdopen,
   81         .vop_close              = vop_stdclose,
   82         .vop_pathconf           = vop_stdpathconf,
   83         .vop_readlink           = (void *)vop_einval,
   84         .vop_reallocblks        = (void *)vop_eopnotsupp,
   85         .vop_strategy           = vop_nostrategy,
   86         .vop_getacl             = (void *)vop_eopnotsupp,
   87         .vop_setacl             = (void *)vop_eopnotsupp,
   88         .vop_aclcheck           = (void *)vop_eopnotsupp,
   89         .vop_getextattr         = (void *)vop_eopnotsupp,
   90         .vop_setextattr         = (void *)vop_eopnotsupp,
   91         .vop_markatime          = vop_stdmarkatime,
   92         .vop_nresolve           = vop_compat_nresolve,
   93         .vop_nlookupdotdot      = vop_compat_nlookupdotdot,
   94         .vop_ncreate            = vop_compat_ncreate,
   95         .vop_nmkdir             = vop_compat_nmkdir,
   96         .vop_nmknod             = vop_compat_nmknod,
   97         .vop_nlink              = vop_compat_nlink,
   98         .vop_nsymlink           = vop_compat_nsymlink,
   99         .vop_nwhiteout          = vop_compat_nwhiteout,
  100         .vop_nremove            = vop_compat_nremove,
  101         .vop_nrmdir             = vop_compat_nrmdir,
  102         .vop_nrename            = vop_compat_nrename,
  103         .vop_mountctl           = vop_stdmountctl
  104 };
  105 
  106 VNODEOP_SET(default_vnode_vops);
  107 
  108 int
  109 vop_eopnotsupp(struct vop_generic_args *ap)
  110 {
  111         return (EOPNOTSUPP);
  112 }
  113 
  114 int
  115 vop_ebadf(struct vop_generic_args *ap)
  116 {
  117         return (EBADF);
  118 }
  119 
  120 int
  121 vop_enotty(struct vop_generic_args *ap)
  122 {
  123         return (ENOTTY);
  124 }
  125 
  126 int
  127 vop_einval(struct vop_generic_args *ap)
  128 {
  129         return (EINVAL);
  130 }
  131 
  132 int
  133 vop_stdmarkatime(struct vop_markatime_args *ap)
  134 {
  135         return (EOPNOTSUPP);
  136 }
  137 
  138 int
  139 vop_null(struct vop_generic_args *ap)
  140 {
  141         return (0);
  142 }
  143 
  144 int
  145 vop_defaultop(struct vop_generic_args *ap)
  146 {
  147         return (VOCALL(&default_vnode_vops, ap));
  148 }
  149 
  150 int
  151 vop_panic(struct vop_generic_args *ap)
  152 {
  153         panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name);
  154 }
  155 
  156 /*
  157  * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp }
  158  * XXX STOPGAP FUNCTION
  159  *
  160  * XXX OLD API ROUTINE!  WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE
  161  * WILL BE REMOVED.  This procedure exists for all VFSs which have not
  162  * yet implemented VOP_NRESOLVE().  It converts VOP_NRESOLVE() into a 
  163  * vop_old_lookup() and does appropriate translations.
  164  *
  165  * Resolve a ncp for VFSs which do not support the VOP.  Eventually all
  166  * VFSs will support this VOP and this routine can be removed, since
  167  * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP
  168  * API.
  169  *
  170  * A locked ncp is passed in to be resolved.  The NCP is resolved by
  171  * figuring out the vnode (if any) and calling cache_setvp() to attach the
  172  * vnode to the entry.  If the entry represents a non-existant node then
  173  * cache_setvp() is called with a NULL vnode to resolve the entry into a
  174  * negative cache entry.  No vnode locks are retained and the
  175  * ncp is left locked on return.
  176  *
  177  * The ncp will NEVER represent "", "." or "..", or contain any slashes.
  178  *
  179  * There is a potential directory and vnode interlock.   The lock order
  180  * requirement is: namecache, governing directory, resolved vnode.
  181  */
  182 int
  183 vop_compat_nresolve(struct vop_nresolve_args *ap)
  184 {
  185         int error;
  186         struct vnode *dvp;
  187         struct vnode *vp;
  188         struct nchandle *nch;
  189         struct namecache *ncp;
  190         struct componentname cnp;
  191 
  192         nch = ap->a_nch;        /* locked namecache node */
  193         ncp = nch->ncp;
  194         dvp = ap->a_dvp;
  195 
  196         /*
  197          * UFS currently stores all sorts of side effects, including a loop
  198          * variable, in the directory inode.  That needs to be fixed and the
  199          * other VFS's audited before we can switch to LK_SHARED.
  200          */
  201         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  202                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  203                         ncp, ncp->nc_name);
  204                 return(EAGAIN);
  205         }
  206 
  207         bzero(&cnp, sizeof(cnp));
  208         cnp.cn_nameiop = NAMEI_LOOKUP;
  209         cnp.cn_flags = 0;
  210         cnp.cn_nameptr = ncp->nc_name;
  211         cnp.cn_namelen = ncp->nc_nlen;
  212         cnp.cn_cred = ap->a_cred;
  213         cnp.cn_td = curthread; /* XXX */
  214 
  215         /*
  216          * vop_old_lookup() always returns vp locked.  dvp may or may not be
  217          * left locked depending on CNP_PDIRUNLOCK.
  218          */
  219         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
  220         if (error == 0)
  221                 vn_unlock(vp);
  222         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  223                 vn_unlock(dvp);
  224         if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
  225                 /* was resolved by another process while we were unlocked */
  226                 if (error == 0)
  227                         vrele(vp);
  228         } else if (error == 0) {
  229                 KKASSERT(vp != NULL);
  230                 cache_setvp(nch, vp);
  231                 vrele(vp);
  232         } else if (error == ENOENT) {
  233                 KKASSERT(vp == NULL);
  234                 if (cnp.cn_flags & CNP_ISWHITEOUT)
  235                         ncp->nc_flag |= NCF_WHITEOUT;
  236                 cache_setvp(nch, NULL);
  237         }
  238         vrele(dvp);
  239         return (error);
  240 }
  241 
  242 /*
  243  * vop_compat_nlookupdotdot { struct vnode *a_dvp,
  244  *                      struct vnode **a_vpp,
  245  *                      struct ucred *a_cred }
  246  *
  247  * Lookup the vnode representing the parent directory of the specified
  248  * directory vnode.  a_dvp should not be locked.  If no error occurs *a_vpp
  249  * will contained the parent vnode, locked and refd, else *a_vpp will be NULL.
  250  *
  251  * This function is designed to aid NFS server-side operations and is
  252  * used by cache_fromdvp() to create a consistent, connected namecache
  253  * topology.
  254  *
  255  * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT
  256  * code out from their *_lookup() and create *_nlookupdotdot().  Then as time
  257  * permits VFSs will implement the remaining *_n*() calls and finally get
  258  * rid of their *_lookup() call.
  259  */
  260 int
  261 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap)
  262 {
  263         struct componentname cnp;
  264         int error;
  265 
  266         /*
  267          * UFS currently stores all sorts of side effects, including a loop
  268          * variable, in the directory inode.  That needs to be fixed and the
  269          * other VFS's audited before we can switch to LK_SHARED.
  270          */
  271         *ap->a_vpp = NULL;
  272         if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0)
  273                 return (error);
  274         if (ap->a_dvp->v_type != VDIR) {
  275                 vput(ap->a_dvp);
  276                 return (ENOTDIR);
  277         }
  278 
  279         bzero(&cnp, sizeof(cnp));
  280         cnp.cn_nameiop = NAMEI_LOOKUP;
  281         cnp.cn_flags = CNP_ISDOTDOT;
  282         cnp.cn_nameptr = "..";
  283         cnp.cn_namelen = 2;
  284         cnp.cn_cred = ap->a_cred;
  285         cnp.cn_td = curthread; /* XXX */
  286 
  287         /*
  288          * vop_old_lookup() always returns vp locked.  dvp may or may not be
  289          * left locked depending on CNP_PDIRUNLOCK.
  290          *
  291          * (*vpp) will be returned locked if no error occured, which is the
  292          * state we want.
  293          */
  294         error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp);
  295         if (cnp.cn_flags & CNP_PDIRUNLOCK)
  296                 vrele(ap->a_dvp);
  297         else
  298                 vput(ap->a_dvp);
  299         return (error);
  300 }
  301 
  302 /*
  303  * vop_compat_ncreate { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
  304  *                      struct vnode *a_dvp,
  305  *                      struct vnode **a_vpp,
  306  *                      struct ucred *a_cred,
  307  *                      struct vattr *a_vap }
  308  *
  309  * Create a file as specified by a_vap.  Compatibility requires us to issue
  310  * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order
  311  * to setup the directory inode's i_offset and i_count (e.g. in UFS).
  312  */
  313 int
  314 vop_compat_ncreate(struct vop_ncreate_args *ap)
  315 {
  316         struct thread *td = curthread;
  317         struct componentname cnp;
  318         struct nchandle *nch;
  319         struct namecache *ncp;
  320         struct vnode *dvp;
  321         int error;
  322 
  323         /*
  324          * Sanity checks, get a locked directory vnode.
  325          */
  326         nch = ap->a_nch;                /* locked namecache node */
  327         dvp = ap->a_dvp;
  328         ncp = nch->ncp;
  329 
  330         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  331                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  332                         ncp, ncp->nc_name);
  333                 return(EAGAIN);
  334         }
  335 
  336         /*
  337          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  338          * caches all information required to create the entry in the
  339          * directory inode.  We expect a return code of EJUSTRETURN for
  340          * the CREATE case.  The cnp must simulated a saved-name situation.
  341          */
  342         bzero(&cnp, sizeof(cnp));
  343         cnp.cn_nameiop = NAMEI_CREATE;
  344         cnp.cn_flags = CNP_LOCKPARENT;
  345         cnp.cn_nameptr = ncp->nc_name;
  346         cnp.cn_namelen = ncp->nc_nlen;
  347         cnp.cn_cred = ap->a_cred;
  348         cnp.cn_td = td;
  349         *ap->a_vpp = NULL;
  350 
  351         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
  352 
  353         /*
  354          * EJUSTRETURN should be returned for this case, which means that
  355          * the VFS has setup the directory inode for the create.  The dvp we
  356          * passed in is expected to remain in a locked state.
  357          *
  358          * If the VOP_OLD_CREATE is successful we are responsible for updating
  359          * the cache state of the locked ncp that was passed to us.
  360          */
  361         if (error == EJUSTRETURN) {
  362                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  363                 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap);
  364                 if (error == 0) {
  365                         cache_setunresolved(nch);
  366                         cache_setvp(nch, *ap->a_vpp);
  367                 }
  368         } else {
  369                 if (error == 0) {
  370                         vput(*ap->a_vpp);
  371                         *ap->a_vpp = NULL;
  372                         error = EEXIST;
  373                 }
  374                 KKASSERT(*ap->a_vpp == NULL);
  375         }
  376         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  377                 vn_unlock(dvp);
  378         vrele(dvp);
  379         return (error);
  380 }
  381 
  382 /*
  383  * vop_compat_nmkdir { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
  384  *                      struct vnode *a_dvp,
  385  *                      struct vnode **a_vpp,
  386  *                      struct ucred *a_cred,
  387  *                      struct vattr *a_vap }
  388  *
  389  * Create a directory as specified by a_vap.  Compatibility requires us to
  390  * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in
  391  * order to setup the directory inode's i_offset and i_count (e.g. in UFS).
  392  */
  393 int
  394 vop_compat_nmkdir(struct vop_nmkdir_args *ap)
  395 {
  396         struct thread *td = curthread;
  397         struct componentname cnp;
  398         struct nchandle *nch;
  399         struct namecache *ncp;
  400         struct vnode *dvp;
  401         int error;
  402 
  403         /*
  404          * Sanity checks, get a locked directory vnode.
  405          */
  406         nch = ap->a_nch;                /* locked namecache node */
  407         ncp = nch->ncp;
  408         dvp = ap->a_dvp;
  409         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  410                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  411                         ncp, ncp->nc_name);
  412                 return(EAGAIN);
  413         }
  414 
  415         /*
  416          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  417          * caches all information required to create the entry in the
  418          * directory inode.  We expect a return code of EJUSTRETURN for
  419          * the CREATE case.  The cnp must simulated a saved-name situation.
  420          */
  421         bzero(&cnp, sizeof(cnp));
  422         cnp.cn_nameiop = NAMEI_CREATE;
  423         cnp.cn_flags = CNP_LOCKPARENT;
  424         cnp.cn_nameptr = ncp->nc_name;
  425         cnp.cn_namelen = ncp->nc_nlen;
  426         cnp.cn_cred = ap->a_cred;
  427         cnp.cn_td = td;
  428         *ap->a_vpp = NULL;
  429 
  430         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
  431 
  432         /*
  433          * EJUSTRETURN should be returned for this case, which means that
  434          * the VFS has setup the directory inode for the create.  The dvp we
  435          * passed in is expected to remain in a locked state.
  436          *
  437          * If the VOP_OLD_MKDIR is successful we are responsible for updating
  438          * the cache state of the locked ncp that was passed to us.
  439          */
  440         if (error == EJUSTRETURN) {
  441                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  442                 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap);
  443                 if (error == 0) {
  444                         cache_setunresolved(nch);
  445                         cache_setvp(nch, *ap->a_vpp);
  446                 }
  447         } else {
  448                 if (error == 0) {
  449                         vput(*ap->a_vpp);
  450                         *ap->a_vpp = NULL;
  451                         error = EEXIST;
  452                 }
  453                 KKASSERT(*ap->a_vpp == NULL);
  454         }
  455         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  456                 vn_unlock(dvp);
  457         vrele(dvp);
  458         return (error);
  459 }
  460 
  461 /*
  462  * vop_compat_nmknod { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
  463  *                      struct vnode *a_dvp,
  464  *                      struct vnode **a_vpp,
  465  *                      struct ucred *a_cred,
  466  *                      struct vattr *a_vap }
  467  *
  468  * Create a device or fifo node as specified by a_vap.  Compatibility requires
  469  * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD
  470  * in order to setup the directory inode's i_offset and i_count (e.g. in UFS).
  471  */
  472 int
  473 vop_compat_nmknod(struct vop_nmknod_args *ap)
  474 {
  475         struct thread *td = curthread;
  476         struct componentname cnp;
  477         struct nchandle *nch;
  478         struct namecache *ncp;
  479         struct vnode *dvp;
  480         int error;
  481 
  482         /*
  483          * Sanity checks, get a locked directory vnode.
  484          */
  485         nch = ap->a_nch;                /* locked namecache node */
  486         ncp = nch->ncp;
  487         dvp = ap->a_dvp;
  488 
  489         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  490                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  491                         ncp, ncp->nc_name);
  492                 return(EAGAIN);
  493         }
  494 
  495         /*
  496          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  497          * caches all information required to create the entry in the
  498          * directory inode.  We expect a return code of EJUSTRETURN for
  499          * the CREATE case.  The cnp must simulated a saved-name situation.
  500          */
  501         bzero(&cnp, sizeof(cnp));
  502         cnp.cn_nameiop = NAMEI_CREATE;
  503         cnp.cn_flags = CNP_LOCKPARENT;
  504         cnp.cn_nameptr = ncp->nc_name;
  505         cnp.cn_namelen = ncp->nc_nlen;
  506         cnp.cn_cred = ap->a_cred;
  507         cnp.cn_td = td;
  508         *ap->a_vpp = NULL;
  509 
  510         error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp);
  511 
  512         /*
  513          * EJUSTRETURN should be returned for this case, which means that
  514          * the VFS has setup the directory inode for the create.  The dvp we
  515          * passed in is expected to remain in a locked state.
  516          *
  517          * If the VOP_OLD_MKNOD is successful we are responsible for updating
  518          * the cache state of the locked ncp that was passed to us.
  519          */
  520         if (error == EJUSTRETURN) {
  521                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  522                 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap);
  523                 if (error == 0) {
  524                         cache_setunresolved(nch);
  525                         cache_setvp(nch, *ap->a_vpp);
  526                 }
  527         } else {
  528                 if (error == 0) {
  529                         vput(*ap->a_vpp);
  530                         *ap->a_vpp = NULL;
  531                         error = EEXIST;
  532                 }
  533                 KKASSERT(*ap->a_vpp == NULL);
  534         }
  535         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  536                 vn_unlock(dvp);
  537         vrele(dvp);
  538         return (error);
  539 }
  540 
  541 /*
  542  * vop_compat_nlink { struct nchandle *a_nch,   XXX STOPGAP FUNCTION
  543  *                      struct vnode *a_dvp,
  544  *                      struct vnode *a_vp,
  545  *                      struct ucred *a_cred }
  546  *
  547  * The passed vp is locked and represents the source.  The passed ncp is
  548  * locked and represents the target to create.
  549  */
  550 int
  551 vop_compat_nlink(struct vop_nlink_args *ap)
  552 {
  553         struct thread *td = curthread;
  554         struct componentname cnp;
  555         struct nchandle *nch;
  556         struct namecache *ncp;
  557         struct vnode *dvp;
  558         struct vnode *tvp;
  559         int error;
  560 
  561         /*
  562          * Sanity checks, get a locked directory vnode.
  563          */
  564         nch = ap->a_nch;                /* locked namecache node */
  565         ncp = nch->ncp;
  566         dvp = ap->a_dvp;
  567 
  568         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  569                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  570                         ncp, ncp->nc_name);
  571                 return(EAGAIN);
  572         }
  573 
  574         /*
  575          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  576          * caches all information required to create the entry in the
  577          * directory inode.  We expect a return code of EJUSTRETURN for
  578          * the CREATE case.  The cnp must simulated a saved-name situation.
  579          *
  580          * It should not be possible for there to be a vnode collision
  581          * between the source vp and target (name lookup).  However NFS
  582          * clients racing each other can cause NFS to alias the same vnode
  583          * across several names without the rest of the system knowing it.
  584          * Use CNP_NOTVP to avoid a panic in this situation.
  585          */
  586         bzero(&cnp, sizeof(cnp));
  587         cnp.cn_nameiop = NAMEI_CREATE;
  588         cnp.cn_flags = CNP_LOCKPARENT | CNP_NOTVP;
  589         cnp.cn_nameptr = ncp->nc_name;
  590         cnp.cn_namelen = ncp->nc_nlen;
  591         cnp.cn_cred = ap->a_cred;
  592         cnp.cn_td = td;
  593         cnp.cn_notvp = ap->a_vp;
  594 
  595         tvp = NULL;
  596         error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp);
  597 
  598         /*
  599          * EJUSTRETURN should be returned for this case, which means that
  600          * the VFS has setup the directory inode for the create.  The dvp we
  601          * passed in is expected to remain in a locked state.
  602          *
  603          * If the VOP_OLD_LINK is successful we are responsible for updating
  604          * the cache state of the locked ncp that was passed to us.
  605          */
  606         if (error == EJUSTRETURN) {
  607                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  608                 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp);
  609                 if (error == 0) {
  610                         cache_setunresolved(nch);
  611                         cache_setvp(nch, ap->a_vp);
  612                 }
  613         } else {
  614                 if (error == 0) {
  615                         vput(tvp);
  616                         error = EEXIST;
  617                 }
  618         }
  619         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  620                 vn_unlock(dvp);
  621         vrele(dvp);
  622         return (error);
  623 }
  624 
  625 int
  626 vop_compat_nsymlink(struct vop_nsymlink_args *ap)
  627 {
  628         struct thread *td = curthread;
  629         struct componentname cnp;
  630         struct nchandle *nch;
  631         struct namecache *ncp;
  632         struct vnode *dvp;
  633         struct vnode *vp;
  634         int error;
  635 
  636         /*
  637          * Sanity checks, get a locked directory vnode.
  638          */
  639         *ap->a_vpp = NULL;
  640         nch = ap->a_nch;                /* locked namecache node */
  641         ncp = nch->ncp;
  642         dvp = ap->a_dvp;
  643 
  644         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  645                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  646                         ncp, ncp->nc_name);
  647                 return(EAGAIN);
  648         }
  649 
  650         /*
  651          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  652          * caches all information required to create the entry in the
  653          * directory inode.  We expect a return code of EJUSTRETURN for
  654          * the CREATE case.  The cnp must simulated a saved-name situation.
  655          */
  656         bzero(&cnp, sizeof(cnp));
  657         cnp.cn_nameiop = NAMEI_CREATE;
  658         cnp.cn_flags = CNP_LOCKPARENT;
  659         cnp.cn_nameptr = ncp->nc_name;
  660         cnp.cn_namelen = ncp->nc_nlen;
  661         cnp.cn_cred = ap->a_cred;
  662         cnp.cn_td = td;
  663 
  664         vp = NULL;
  665         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
  666 
  667         /*
  668          * EJUSTRETURN should be returned for this case, which means that
  669          * the VFS has setup the directory inode for the create.  The dvp we
  670          * passed in is expected to remain in a locked state.
  671          *
  672          * If the VOP_OLD_SYMLINK is successful we are responsible for updating
  673          * the cache state of the locked ncp that was passed to us.
  674          */
  675         if (error == EJUSTRETURN) {
  676                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  677                 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target);
  678                 if (error == 0) {
  679                         cache_setunresolved(nch);
  680                         cache_setvp(nch, vp);
  681                         *ap->a_vpp = vp;
  682                 }
  683         } else {
  684                 if (error == 0) {
  685                         vput(vp);
  686                         vp = NULL;
  687                         error = EEXIST;
  688                 }
  689                 KKASSERT(vp == NULL);
  690         }
  691         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  692                 vn_unlock(dvp);
  693         vrele(dvp);
  694         return (error);
  695 }
  696 
  697 /*
  698  * vop_compat_nwhiteout { struct nchandle *a_nch,       XXX STOPGAP FUNCTION
  699  *                        struct vnode *a_dvp,
  700  *                        struct ucred *a_cred,
  701  *                        int a_flags }
  702  *
  703  * Issie a whiteout operation (create, lookup, or delete).  Compatibility 
  704  * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue 
  705  * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count
  706  * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops.  For NAMEI_LOOKUP
  707  * no lookup is necessary.
  708  */
  709 int
  710 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap)
  711 {
  712         struct thread *td = curthread;
  713         struct componentname cnp;
  714         struct nchandle *nch;
  715         struct namecache *ncp;
  716         struct vnode *dvp;
  717         struct vnode *vp;
  718         int error;
  719 
  720         /*
  721          * Sanity checks, get a locked directory vnode.
  722          */
  723         nch = ap->a_nch;                /* locked namecache node */
  724         ncp = nch->ncp;
  725         dvp = ap->a_dvp;
  726 
  727         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  728                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  729                         ncp, ncp->nc_name);
  730                 return(EAGAIN);
  731         }
  732 
  733         /*
  734          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  735          * caches all information required to create the entry in the
  736          * directory inode.  We expect a return code of EJUSTRETURN for
  737          * the CREATE case.  The cnp must simulated a saved-name situation.
  738          */
  739         bzero(&cnp, sizeof(cnp));
  740         cnp.cn_nameiop = ap->a_flags;
  741         cnp.cn_flags = CNP_LOCKPARENT;
  742         cnp.cn_nameptr = ncp->nc_name;
  743         cnp.cn_namelen = ncp->nc_nlen;
  744         cnp.cn_cred = ap->a_cred;
  745         cnp.cn_td = td;
  746 
  747         vp = NULL;
  748 
  749         /*
  750          * EJUSTRETURN should be returned for the CREATE or DELETE cases.
  751          * The VFS has setup the directory inode for the create.  The dvp we
  752          * passed in is expected to remain in a locked state.
  753          *
  754          * If the VOP_OLD_WHITEOUT is successful we are responsible for updating
  755          * the cache state of the locked ncp that was passed to us.
  756          */
  757         switch(ap->a_flags) {
  758         case NAMEI_DELETE:
  759                 cnp.cn_flags |= CNP_DOWHITEOUT;
  760                 /* fall through */
  761         case NAMEI_CREATE:
  762                 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
  763                 if (error == EJUSTRETURN) {
  764                         KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  765                         error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags);
  766                         if (error == 0)
  767                                 cache_setunresolved(nch);
  768                 } else {
  769                         if (error == 0) {
  770                                 vput(vp);
  771                                 vp = NULL;
  772                                 error = EEXIST;
  773                         }
  774                         KKASSERT(vp == NULL);
  775                 }
  776                 break;
  777         case NAMEI_LOOKUP:
  778                 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags);
  779                 break;
  780         default:
  781                 error = EINVAL;
  782                 break;
  783         }
  784         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  785                 vn_unlock(dvp);
  786         vrele(dvp);
  787         return (error);
  788 }
  789 
  790 
  791 /*
  792  * vop_compat_nremove { struct nchandle *a_nch,         XXX STOPGAP FUNCTION
  793  *                      struct vnode *a_dvp,
  794  *                      struct ucred *a_cred }
  795  */
  796 int
  797 vop_compat_nremove(struct vop_nremove_args *ap)
  798 {
  799         struct thread *td = curthread;
  800         struct componentname cnp;
  801         struct nchandle *nch;
  802         struct namecache *ncp;
  803         struct vnode *dvp;
  804         struct vnode *vp;
  805         int error;
  806 
  807         /*
  808          * Sanity checks, get a locked directory vnode.
  809          */
  810         nch = ap->a_nch;                /* locked namecache node */
  811         ncp = nch->ncp;
  812         dvp = ap->a_dvp;
  813 
  814         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  815                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  816                         ncp, ncp->nc_name);
  817                 return(EAGAIN);
  818         }
  819 
  820         /*
  821          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  822          * caches all information required to delete the entry in the
  823          * directory inode.  We expect a return code of 0 for the DELETE
  824          * case (meaning that a vp has been found).  The cnp must simulated
  825          * a saved-name situation.
  826          */
  827         bzero(&cnp, sizeof(cnp));
  828         cnp.cn_nameiop = NAMEI_DELETE;
  829         cnp.cn_flags = CNP_LOCKPARENT;
  830         cnp.cn_nameptr = ncp->nc_name;
  831         cnp.cn_namelen = ncp->nc_nlen;
  832         cnp.cn_cred = ap->a_cred;
  833         cnp.cn_td = td;
  834 
  835         /*
  836          * The vnode must be a directory and must not represent the
  837          * current directory.
  838          */
  839         vp = NULL;
  840         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
  841         if (error == 0 && vp->v_type == VDIR)
  842                 error = EPERM;
  843         if (error == 0) {
  844                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  845                 error = VOP_OLD_REMOVE(dvp, vp, &cnp);
  846                 if (error == 0)
  847                         cache_unlink(nch);
  848         }
  849         if (vp) {
  850                 if (dvp == vp)
  851                         vrele(vp);
  852                 else    
  853                         vput(vp);
  854         }
  855         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  856                 vn_unlock(dvp);
  857         vrele(dvp);
  858         return (error);
  859 }
  860 
  861 /*
  862  * vop_compat_nrmdir { struct nchandle *a_nch,  XXX STOPGAP FUNCTION
  863  *                     struct vnode *dvp,
  864  *                     struct ucred *a_cred }
  865  */
  866 int
  867 vop_compat_nrmdir(struct vop_nrmdir_args *ap)
  868 {
  869         struct thread *td = curthread;
  870         struct componentname cnp;
  871         struct nchandle *nch;
  872         struct namecache *ncp;
  873         struct vnode *dvp;
  874         struct vnode *vp;
  875         int error;
  876 
  877         /*
  878          * Sanity checks, get a locked directory vnode.
  879          */
  880         nch = ap->a_nch;                /* locked namecache node */
  881         ncp = nch->ncp;
  882         dvp = ap->a_dvp;
  883 
  884         if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
  885                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  886                         ncp, ncp->nc_name);
  887                 return(EAGAIN);
  888         }
  889 
  890         /*
  891          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
  892          * caches all information required to delete the entry in the
  893          * directory inode.  We expect a return code of 0 for the DELETE
  894          * case (meaning that a vp has been found).  The cnp must simulated
  895          * a saved-name situation.
  896          */
  897         bzero(&cnp, sizeof(cnp));
  898         cnp.cn_nameiop = NAMEI_DELETE;
  899         cnp.cn_flags = CNP_LOCKPARENT;
  900         cnp.cn_nameptr = ncp->nc_name;
  901         cnp.cn_namelen = ncp->nc_nlen;
  902         cnp.cn_cred = ap->a_cred;
  903         cnp.cn_td = td;
  904 
  905         /*
  906          * The vnode must be a directory and must not represent the
  907          * current directory.
  908          */
  909         vp = NULL;
  910         error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp);
  911         if (error == 0 && vp->v_type != VDIR)
  912                 error = ENOTDIR;
  913         if (error == 0 && vp == dvp)
  914                 error = EINVAL;
  915         if (error == 0 && (vp->v_flag & VROOT))
  916                 error = EBUSY;
  917         if (error == 0) {
  918                 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0);
  919                 error = VOP_OLD_RMDIR(dvp, vp, &cnp);
  920 
  921                 /*
  922                  * Note that this invalidation will cause any process
  923                  * currently CD'd into the directory being removed to be
  924                  * disconnected from the topology and not be able to ".."
  925                  * back out.
  926                  */
  927                 if (error == 0) {
  928                         cache_inval(nch, CINV_DESTROY);
  929                         cache_inval_vp(vp, CINV_DESTROY);
  930                 }
  931         }
  932         if (vp) {
  933                 if (dvp == vp)
  934                         vrele(vp);
  935                 else    
  936                         vput(vp);
  937         }
  938         if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0)
  939                 vn_unlock(dvp);
  940         vrele(dvp);
  941         return (error);
  942 }
  943 
  944 /*
  945  * vop_compat_nrename { struct nchandle *a_fnch,        XXX STOPGAP FUNCTION
  946  *                      struct nchandle *a_tnch,
  947  *                      struct ucred *a_cred }
  948  *
  949  * This is a fairly difficult procedure.  The old VOP_OLD_RENAME requires that
  950  * the source directory and vnode be unlocked and the target directory and
  951  * vnode (if it exists) be locked.  All arguments will be vrele'd and 
  952  * the targets will also be unlocked regardless of the return code.
  953  */
  954 int
  955 vop_compat_nrename(struct vop_nrename_args *ap)
  956 {
  957         struct thread *td = curthread;
  958         struct componentname fcnp;
  959         struct componentname tcnp;
  960         struct nchandle *fnch;
  961         struct nchandle *tnch;
  962         struct namecache *fncp;
  963         struct namecache *tncp;
  964         struct vnode *fdvp, *fvp;
  965         struct vnode *tdvp, *tvp;
  966         int error;
  967 
  968         /*
  969          * Sanity checks, get referenced vnodes representing the source.
  970          */
  971         fnch = ap->a_fnch;              /* locked namecache node */
  972         fncp = fnch->ncp;
  973         fdvp = ap->a_fdvp;
  974 
  975         /*
  976          * Temporarily lock the source directory and lookup in DELETE mode to
  977          * check permissions.  XXX delete permissions should have been
  978          * checked by nlookup(), we need to add NLC_DELETE for delete
  979          * checking.  It is unclear whether VFS's require the directory setup
  980          * info NAMEI_DELETE causes to be stored in the fdvp's inode, but
  981          * since it isn't locked and since UFS always does a relookup of
  982          * the source, it is believed that the only side effect that matters
  983          * is the permissions check.
  984          */
  985         if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) {
  986                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
  987                         fncp, fncp->nc_name);
  988                 return(EAGAIN);
  989         }
  990 
  991         bzero(&fcnp, sizeof(fcnp));
  992         fcnp.cn_nameiop = NAMEI_DELETE;
  993         fcnp.cn_flags = CNP_LOCKPARENT;
  994         fcnp.cn_nameptr = fncp->nc_name;
  995         fcnp.cn_namelen = fncp->nc_nlen;
  996         fcnp.cn_cred = ap->a_cred;
  997         fcnp.cn_td = td;
  998 
  999         /*
 1000          * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked
 1001          * fvp.
 1002          */
 1003         fvp = NULL;
 1004         error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp);
 1005         if (error == 0 && (fvp->v_flag & VROOT)) {
 1006                 vput(fvp);      /* as if vop_old_lookup had failed */
 1007                 error = EBUSY;
 1008         }
 1009         if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) {
 1010                 fcnp.cn_flags |= CNP_PDIRUNLOCK;
 1011                 vn_unlock(fdvp);
 1012         }
 1013         if (error) {
 1014                 vrele(fdvp);
 1015                 return (error);
 1016         }
 1017         vn_unlock(fvp);
 1018 
 1019         /*
 1020          * fdvp and fvp are now referenced and unlocked.
 1021          *
 1022          * Get a locked directory vnode for the target and lookup the target
 1023          * in CREATE mode so it places the required information in the
 1024          * directory inode.
 1025          */
 1026         tnch = ap->a_tnch;              /* locked namecache node */
 1027         tncp = tnch->ncp;
 1028         tdvp = ap->a_tdvp;
 1029         if (error) {
 1030                 vrele(fdvp);
 1031                 vrele(fvp);
 1032                 return (error);
 1033         }
 1034         if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) {
 1035                 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n",
 1036                         tncp, tncp->nc_name);
 1037                 vrele(fdvp);
 1038                 vrele(fvp);
 1039                 return(EAGAIN);
 1040         }
 1041 
 1042         /*
 1043          * Setup the cnp for a traditional vop_old_lookup() call.  The lookup
 1044          * caches all information required to create the entry in the
 1045          * target directory inode.
 1046          */
 1047         bzero(&tcnp, sizeof(tcnp));
 1048         tcnp.cn_nameiop = NAMEI_RENAME;
 1049         tcnp.cn_flags = CNP_LOCKPARENT;
 1050         tcnp.cn_nameptr = tncp->nc_name;
 1051         tcnp.cn_namelen = tncp->nc_nlen;
 1052         tcnp.cn_cred = ap->a_cred;
 1053         tcnp.cn_td = td;
 1054 
 1055         tvp = NULL;
 1056         error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp);
 1057 
 1058         if (error == EJUSTRETURN) {
 1059                 /*
 1060                  * Target does not exist.  tvp should be NULL.
 1061                  */
 1062                 KKASSERT(tvp == NULL);
 1063                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
 1064                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
 1065                 if (error == 0)
 1066                         cache_rename(fnch, tnch);
 1067         } else if (error == 0) {
 1068                 /*
 1069                  * Target exists.  VOP_OLD_RENAME should correctly delete the
 1070                  * target.
 1071                  */
 1072                 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0);
 1073                 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp);
 1074                 if (error == 0)
 1075                         cache_rename(fnch, tnch);
 1076         } else {
 1077                 vrele(fdvp);
 1078                 vrele(fvp);
 1079                 if (tcnp.cn_flags & CNP_PDIRUNLOCK)
 1080                         vrele(tdvp);
 1081                 else
 1082                         vput(tdvp);
 1083         }
 1084         return (error);
 1085 }
 1086 
 1087 static int
 1088 vop_nolookup(struct vop_old_lookup_args *ap)
 1089 {
 1090 
 1091         *ap->a_vpp = NULL;
 1092         return (ENOTDIR);
 1093 }
 1094 
 1095 /*
 1096  *      vop_nostrategy:
 1097  *
 1098  *      Strategy routine for VFS devices that have none.
 1099  *
 1100  *      B_ERROR and B_INVAL must be cleared prior to calling any strategy
 1101  *      routine.  Typically this is done for a BUF_CMD_READ strategy call.
 1102  *      Typically B_INVAL is assumed to already be clear prior to a write
 1103  *      and should not be cleared manually unless you just made the buffer
 1104  *      invalid.  B_ERROR should be cleared either way.
 1105  */
 1106 
 1107 static int
 1108 vop_nostrategy (struct vop_strategy_args *ap)
 1109 {
 1110         kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf);
 1111         vprint("", ap->a_vp);
 1112         ap->a_bio->bio_buf->b_flags |= B_ERROR;
 1113         ap->a_bio->bio_buf->b_error = EOPNOTSUPP;
 1114         biodone(ap->a_bio);
 1115         return (EOPNOTSUPP);
 1116 }
 1117 
 1118 int
 1119 vop_stdpathconf(struct vop_pathconf_args *ap)
 1120 {
 1121         int error = 0;
 1122 
 1123         switch (ap->a_name) {
 1124         case _PC_LINK_MAX:
 1125                 *ap->a_retval = LINK_MAX;
 1126                 break;
 1127         case _PC_NAME_MAX:
 1128                 *ap->a_retval = NAME_MAX;
 1129                 break;
 1130         case _PC_PATH_MAX:
 1131                 *ap->a_retval = PATH_MAX;
 1132                 break;
 1133         case _PC_MAX_CANON:
 1134                 *ap->a_retval = MAX_CANON;
 1135                 break;
 1136         case _PC_MAX_INPUT:
 1137                 *ap->a_retval = MAX_INPUT;
 1138                 break;
 1139         case _PC_PIPE_BUF:
 1140                 *ap->a_retval = PIPE_BUF;
 1141                 break;
 1142         case _PC_CHOWN_RESTRICTED:
 1143                 *ap->a_retval = 1;
 1144                 break;
 1145         case _PC_NO_TRUNC:
 1146                 *ap->a_retval = 1;
 1147                 break;
 1148         case _PC_VDISABLE:
 1149                 *ap->a_retval = _POSIX_VDISABLE;
 1150                 break;
 1151         default:
 1152                 error = EINVAL;
 1153                 break;
 1154         }
 1155         return (error);
 1156 }
 1157 
 1158 /*
 1159  * Standard open.
 1160  *
 1161  * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp)
 1162  *
 1163  * a_mode: note, 'F' modes, e.g. FREAD, FWRITE
 1164  */
 1165 int
 1166 vop_stdopen(struct vop_open_args *ap)
 1167 {
 1168         struct vnode *vp = ap->a_vp;
 1169         struct file *fp;
 1170 
 1171         if ((fp = ap->a_fp) != NULL) {
 1172                 switch(vp->v_type) {
 1173                 case VFIFO:
 1174                         fp->f_type = DTYPE_FIFO;
 1175                         break;
 1176                 default:
 1177                         fp->f_type = DTYPE_VNODE;
 1178                         break;
 1179                 }
 1180                 fp->f_flag = ap->a_mode & FMASK;
 1181                 fp->f_ops = &vnode_fileops;
 1182                 fp->f_data = vp;
 1183                 vref(vp);
 1184         }
 1185         if (ap->a_mode & FWRITE)
 1186                 atomic_add_int(&vp->v_writecount, 1);
 1187         KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX);
 1188         atomic_add_int(&vp->v_opencount, 1);
 1189         return (0);
 1190 }
 1191 
 1192 /*
 1193  * Standard close.
 1194  *
 1195  * (struct vnode *a_vp, int a_fflag)
 1196  *
 1197  * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE.  same as a_mode in stdopen?
 1198  */
 1199 int
 1200 vop_stdclose(struct vop_close_args *ap)
 1201 {
 1202         struct vnode *vp = ap->a_vp;
 1203 
 1204         KASSERT(vp->v_opencount > 0,
 1205                 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x",
 1206                 vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag));
 1207         if (ap->a_fflag & FWRITE) {
 1208                 KASSERT(vp->v_writecount > 0,
 1209                         ("VOP_STDCLOSE: BAD WRITECOUNT %p %d",
 1210                         vp, vp->v_writecount));
 1211                 atomic_add_int(&vp->v_writecount, -1);
 1212         }
 1213         atomic_add_int(&vp->v_opencount, -1);
 1214         return (0);
 1215 }
 1216 
 1217 /*
 1218  * Implement standard getpages and putpages.  All filesystems must use
 1219  * the buffer cache to back regular files.
 1220  */
 1221 int
 1222 vop_stdgetpages(struct vop_getpages_args *ap)
 1223 {
 1224         struct mount *mp;
 1225         int error;
 1226 
 1227         if ((mp = ap->a_vp->v_mount) != NULL) {
 1228                 error = vnode_pager_generic_getpages(
 1229                                 ap->a_vp, ap->a_m, ap->a_count,
 1230                                 ap->a_reqpage, ap->a_seqaccess);
 1231         } else {
 1232                 error = VM_PAGER_BAD;
 1233         }
 1234         return (error);
 1235 }
 1236 
 1237 int
 1238 vop_stdputpages(struct vop_putpages_args *ap)
 1239 {
 1240         struct mount *mp;
 1241         int error;
 1242 
 1243         if ((mp = ap->a_vp->v_mount) != NULL) {
 1244                 error = vnode_pager_generic_putpages(
 1245                                 ap->a_vp, ap->a_m, ap->a_count,
 1246                                 ap->a_sync, ap->a_rtvals);
 1247         } else {
 1248                 error = VM_PAGER_BAD;
 1249         }
 1250         return (error);
 1251 }
 1252 
 1253 int
 1254 vop_stdnoread(struct vop_read_args *ap)
 1255 {
 1256         return (EINVAL);
 1257 }
 1258 
 1259 int
 1260 vop_stdnowrite(struct vop_write_args *ap)
 1261 {
 1262         return (EINVAL);
 1263 }
 1264 
 1265 /* 
 1266  * vfs default ops
 1267  * used to fill the vfs fucntion table to get reasonable default return values.
 1268  */
 1269 int 
 1270 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
 1271 {
 1272         return (0);
 1273 }
 1274 
 1275 int     
 1276 vfs_stdunmount(struct mount *mp, int mntflags)
 1277 {
 1278         return (0);
 1279 }
 1280 
 1281 int
 1282 vop_stdmountctl(struct vop_mountctl_args *ap)
 1283 {
 1284 
 1285         struct mount *mp;
 1286         int error = 0;
 1287 
 1288         mp = ap->a_head.a_ops->head.vv_mount;
 1289 
 1290         switch(ap->a_op) {
 1291         case MOUNTCTL_MOUNTFLAGS:
 1292                 /*
 1293                  * Get a string buffer with all the mount flags
 1294                  * names comman separated.
 1295                  * mount(2) will use this information.
 1296                  */
 1297                 *ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL,
 1298                                             ap->a_buf, ap->a_buflen, &error);
 1299                 break;
 1300         case MOUNTCTL_INSTALL_VFS_JOURNAL:
 1301         case MOUNTCTL_RESTART_VFS_JOURNAL:
 1302         case MOUNTCTL_REMOVE_VFS_JOURNAL:
 1303         case MOUNTCTL_RESYNC_VFS_JOURNAL:
 1304         case MOUNTCTL_STATUS_VFS_JOURNAL:
 1305                 error = journal_mountctl(ap);
 1306                 break;
 1307         default:
 1308                 error = EOPNOTSUPP;
 1309                 break;
 1310         }
 1311         return (error);
 1312 }
 1313 
 1314 int     
 1315 vfs_stdroot(struct mount *mp, struct vnode **vpp)
 1316 {
 1317         return (EOPNOTSUPP);
 1318 }
 1319 
 1320 int     
 1321 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
 1322 {
 1323         return (EOPNOTSUPP);
 1324 }
 1325 
 1326 /*
 1327  * If the VFS does not implement statvfs, then call statfs and convert
 1328  * the values.  This code was taken from libc's __cvtstatvfs() function,
 1329  * contributed by Joerg Sonnenberger.
 1330  */
 1331 int     
 1332 vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
 1333 {
 1334         struct statfs *in;
 1335         int error;
 1336 
 1337         in = &mp->mnt_stat;
 1338         error = VFS_STATFS(mp, in, cred);
 1339         if (error == 0) {
 1340                 bzero(sbp, sizeof(*sbp));
 1341 
 1342                 sbp->f_bsize = in->f_bsize;
 1343                 sbp->f_frsize = in->f_bsize;
 1344                 sbp->f_blocks = in->f_blocks;
 1345                 sbp->f_bfree = in->f_bfree;
 1346                 sbp->f_bavail = in->f_bavail;
 1347                 sbp->f_files = in->f_files;
 1348                 sbp->f_ffree = in->f_ffree;
 1349 
 1350                 /*
 1351                  * XXX
 1352                  * This field counts the number of available inodes to non-root
 1353                  * users, but this information is not available via statfs.
 1354                  * Just ignore this issue by returning the total number 
 1355                  * instead.
 1356                  */
 1357                 sbp->f_favail = in->f_ffree;
 1358 
 1359                 /*
 1360                  * XXX
 1361                  * This field has a different meaning for statfs and statvfs.
 1362                  * For the former it is the cookie exported for NFS and not
 1363                  * intended for normal userland use.
 1364                  */
 1365                 sbp->f_fsid = 0;
 1366 
 1367                 sbp->f_flag = 0;
 1368                 if (in->f_flags & MNT_RDONLY)
 1369                         sbp->f_flag |= ST_RDONLY;
 1370                 if (in->f_flags & MNT_NOSUID)
 1371                         sbp->f_flag |= ST_NOSUID;
 1372                 sbp->f_namemax = 0;
 1373                 sbp->f_owner = in->f_owner;
 1374                 /*
 1375                  * XXX
 1376                  * statfs contains the type as string, statvfs expects it as
 1377                  * enumeration.
 1378                  */
 1379                 sbp->f_type = 0;
 1380 
 1381                 sbp->f_syncreads = in->f_syncreads;
 1382                 sbp->f_syncwrites = in->f_syncwrites;
 1383                 sbp->f_asyncreads = in->f_asyncreads;
 1384                 sbp->f_asyncwrites = in->f_asyncwrites;
 1385         }
 1386         return (error);
 1387 }
 1388 
 1389 int
 1390 vfs_stdvptofh(struct vnode *vp, struct fid *fhp)
 1391 {
 1392         return (EOPNOTSUPP);
 1393 }
 1394 
 1395 int     
 1396 vfs_stdstart(struct mount *mp, int flags)
 1397 {
 1398         return (0);
 1399 }
 1400 
 1401 int     
 1402 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid,
 1403         caddr_t arg, struct ucred *cred)
 1404 {
 1405         return (EOPNOTSUPP);
 1406 }
 1407 
 1408 int     
 1409 vfs_stdsync(struct mount *mp, int waitfor)
 1410 {
 1411         return (0);
 1412 }
 1413 
 1414 int
 1415 vfs_stdnosync(struct mount *mp, int waitfor)
 1416 {
 1417         return (EOPNOTSUPP);
 1418 }
 1419 
 1420 int     
 1421 vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)
 1422 {
 1423         return (EOPNOTSUPP);
 1424 }
 1425 
 1426 int     
 1427 vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp,
 1428               struct fid *fhp, struct vnode **vpp)
 1429 {
 1430         return (EOPNOTSUPP);
 1431 }
 1432 
 1433 int 
 1434 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
 1435         struct ucred **credanonp)
 1436 {
 1437         return (EOPNOTSUPP);
 1438 }
 1439 
 1440 int
 1441 vfs_stdinit(struct vfsconf *vfsp)
 1442 {
 1443         return (0);
 1444 }
 1445 
 1446 int
 1447 vfs_stduninit(struct vfsconf *vfsp)
 1448 {
 1449         return(0);
 1450 }
 1451 
 1452 int
 1453 vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
 1454                  int attrnamespace, const char *attrname,
 1455                  struct ucred *cred)
 1456 {
 1457         return(EOPNOTSUPP);
 1458 }
 1459 
 1460 #define ACCOUNTING_NB_FSTYPES 7
 1461 
 1462 static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
 1463         "ext2fs", "hammer", "mfs", "ntfs", "null", "tmpfs", "ufs" };
 1464 
 1465 int
 1466 vfs_stdac_init(struct mount *mp)
 1467 {
 1468         const char* fs_type;
 1469         int i, fstype_ok = 0;
 1470 
 1471         /* is mounted fs type one we want to do some accounting for ? */
 1472         for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
 1473                 fs_type = accounting_fstypes[i];
 1474                 if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
 1475                                         sizeof(mp->mnt_stat)) == 0) {
 1476                         fstype_ok = 1;
 1477                         break;
 1478                 }
 1479         }
 1480         if (fstype_ok == 0)
 1481                 return (0);
 1482 
 1483         vq_init(mp);
 1484         return (0);
 1485 }
 1486 
 1487 void
 1488 vfs_stdac_done(struct mount *mp)
 1489 {
 1490         vq_done(mp);
 1491 }
 1492 
 1493 void
 1494 vfs_stdncpgen_set(struct mount *mp, struct namecache *ncp)
 1495 {
 1496 }
 1497 
 1498 int
 1499 vfs_stdncpgen_test(struct mount *mp, struct namecache *ncp)
 1500 {
 1501         return 0;
 1502 }
 1503 /* end of vfs default ops */

Cache object: eabccc1b3fe72b4f77ca3ec71b9cd187


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