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/vnode_if.sh

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 #!/bin/sh -
    2 copyright="\
    3 /*
    4  * Copyright (c) 1992, 1993, 1994, 1995
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS \`\`AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 "
   32 SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.77 2022/10/26 23:39:43 riastradh Exp $'
   33 
   34 # Script to produce VFS front-end sugar.
   35 #
   36 # usage: vnode_if.sh srcfile
   37 #       (where srcfile is currently /sys/kern/vnode_if.src)
   38 #
   39 
   40 if [ $# -ne 1 ] ; then
   41         echo 'usage: vnode_if.sh srcfile'
   42         exit 1
   43 fi
   44 
   45 # Name and revision of the source file.
   46 src=$1
   47 SRC_ID=`head -1 $src | sed -e 's/.*\$\(.*\)\$.*/\1/'`
   48 
   49 # Names of the created files.
   50 out_c=vnode_if.c
   51 out_rumpc=../rump/librump/rumpvfs/rumpvnode_if.c
   52 out_h=../sys/vnode_if.h
   53 out_rumph=../rump/include/rump/rumpvnode_if.h
   54 
   55 # generate VNODE_LOCKDEBUG checks (not fully functional)
   56 lockdebug=1
   57 
   58 # Awk program (must support nawk extensions)
   59 # Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
   60 awk=${AWK:-awk}
   61 
   62 # Does this awk have a "toupper" function? (i.e. is it GNU awk)
   63 isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
   64 
   65 # If this awk does not define "toupper" then define our own.
   66 if [ "$isgawk" = TRUE ] ; then
   67         # GNU awk provides it.
   68         toupper=
   69 else
   70         # Provide our own toupper()
   71         toupper='
   72 function toupper(str) {
   73         _toupper_cmd = "echo "str" |tr a-z A-Z"
   74         _toupper_cmd | getline _toupper_str;
   75         close(_toupper_cmd);
   76         return _toupper_str;
   77 }'
   78 fi
   79 
   80 #
   81 # This is the common part of all awk programs that read $src
   82 # This parses the input for one function into the arrays:
   83 #       argdir, argtype, argname, willrele
   84 # and calls "doit()" to generate output for the function.
   85 #
   86 # Input to this parser is pre-processed slightly by sed
   87 # so this awk parser doesn't have to work so hard.  The
   88 # changes done by the sed pre-processing step are:
   89 #       insert a space between * and pointer name
   90 #       replace semicolons with spaces
   91 #
   92 sed_prep='s:\*\([^\*/]\):\* \1:g
   93 s/;/ /'
   94 awk_parser='
   95 # Comment line
   96 /^#/    { next; }
   97 # First line of description
   98 /^vop_/ {
   99         name=$1;
  100         args_name=$1;
  101         argc=0;
  102         have_context=0;
  103         is_context=0;
  104         ncontext=0;
  105         willmake=-1;
  106         fstrans="";
  107         do_pre="";
  108         do_post="";
  109         next;
  110 }
  111 # Last line of description
  112 /^}/    {
  113         doit();
  114         next;
  115 }
  116 # Middle lines of description
  117 {
  118         if ($1 == "VERSION") {
  119                 args_name=args_name "_v" $2;
  120                 next;
  121         } else if ($1 ~ "^FSTRANS=") {
  122                 fstrans = $1;
  123                 sub("FSTRANS=", "", fstrans);
  124                 next;
  125         } else if ($1 ~ "^PRE=") {
  126                 do_pre = $1;
  127                 sub("PRE=", "", do_pre);
  128                 next;
  129         } else if ($1 ~ "^POST=") {
  130                 do_post = $1;
  131                 sub("POST=", "", do_post);
  132                 next;
  133         }
  134 
  135         if ($1 == "CONTEXT") {
  136                 # CONTEXT require PRE and POST handlers.
  137                 if (do_pre == "" || do_post == "")
  138                         next;
  139                 is_context=1;
  140                 have_context=1;
  141         } else {
  142                 if (have_context) {
  143                         # CONTEXT members must come at the end of
  144                         # the args structure, so everything else
  145                         # is ignored.
  146                         next;
  147                 }
  148                 argdir[argc] = $1;
  149         }
  150         i=2;
  151 
  152         if (is_context == 0) {
  153                 if ($2 == "LOCKED=EXCL") {
  154                         lockstate[argc] = "elocked";
  155                         i++;
  156                 } else if ($2 == "LOCKED=YES") {
  157                         lockstate[argc] = "locked";
  158                         i++;
  159                 } else if ($2 == "LOCKED=NO") {
  160                         lockstate[argc] = "unlocked";
  161                         i++;
  162                 } else
  163                         lockstate[argc] = "";
  164 
  165                 if ($2 == "WILLRELE" ||
  166                     $3 == "WILLRELE") {
  167                         willrele[argc] = 1;
  168                         i++;
  169                 } else if ($2 == "WILLPUT" ||
  170                            $3 == "WILLPUT") {
  171                         willrele[argc] = 3;
  172                         i++;
  173                 } else
  174                         willrele[argc] = 0;
  175 
  176                 if ($2 == "WILLMAKE") {
  177                         willmake=argc;
  178                         i++;
  179                 }
  180                 if (argc == 0 && fstrans == "") {
  181                         if (lockstate[0] == "locked" ||
  182                              lockstate[0] == "elocked")
  183                                 fstrans = "NO";
  184                         else
  185                                 fstrans = "YES";
  186                 }
  187         }
  188 
  189         # XXX: replace non-portable types for rump.  We should really
  190         # nuke the types from the kernel, but that is a battle for
  191         # another day.
  192         at = $i;
  193         if (rump) {
  194                 if (at == "vm_prot_t")
  195                         at = "int";
  196                 if (at == "voff_t")
  197                         at = "off_t";
  198                 if (at == "kauth_cred_t")
  199                         at = "struct kauth_cred *"
  200                 if (at == "daddr_t")
  201                         at = "int64_t"
  202         }
  203         argtype[argc + ncontext] = at;
  204         i++;
  205         while (i < NF) {
  206                 argtype[argc + ncontext] = argtype[argc + ncontext]" "$i;
  207                 i++;
  208         }
  209         argname[argc + ncontext] = $i;
  210         if (is_context)
  211                 ncontext++;
  212         else
  213                 argc++;
  214         next;
  215 }
  216 '
  217 
  218 # This is put before the copyright on each generated file.
  219 warning="\
  220 /*      @NetBSD@        */
  221 
  222 /*
  223  * Warning: DO NOT EDIT! This file is automatically generated!
  224  * (Modifications made here may easily be lost!)
  225  *
  226  * Created from the file:
  227  *      ${SRC_ID}
  228  * by the script:
  229  *      ${SCRIPT_ID}
  230  */
  231 "
  232 
  233 # This is to satisfy McKusick (get rid of evil spaces 8^)
  234 anal_retentive='s:\([^/]\*\) :\1:g'
  235 
  236 do_hfile () {
  237 #
  238 # Redirect stdout to the H file.
  239 #
  240 echo "$0: Creating $1" 1>&2
  241 exec > $1
  242 rump=$2
  243 
  244 # Begin stuff
  245 if [ -z "${rump}" ]; then
  246         SYS='SYS_'
  247 else
  248         SYS='RUMP_RUMP'
  249 fi
  250 echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g;s/ $//'
  251 echo ""
  252 echo -n "$copyright"
  253 echo ''
  254 echo "#ifndef _${SYS}VNODE_IF_H_"
  255 echo "#define _${SYS}VNODE_IF_H_"
  256 [ -z "${rump}" ] && echo "
  257 extern const struct vnodeop_desc ${rump}vop_default_desc;"
  258 echo
  259 
  260 # Body stuff
  261 # This awk program needs toupper() so define it if necessary.
  262 sed -e "$sed_prep" $src | $awk -v rump=${rump} "$toupper"'
  263 function doit() {
  264         name = rump name
  265         # Declare arg struct, descriptor.
  266         if (!rump) {
  267                 printf("\n#define %s_DESCOFFSET %d\n",
  268                     toupper(name), vop_offset++);
  269                 printf("struct %s_args {\n", args_name);
  270                 printf("\tconst struct vnodeop_desc * a_desc;\n");
  271                 for (i=0; i<argc; i++) {
  272                         printf("\t%s a_%s;\n", argtype[i], argname[i]);
  273                 }
  274                 for (i=0; i<ncontext; i++) {
  275                         printf("\t%s ctx_%s;\n", argtype[argc+i], \
  276                             argname[argc+i]);
  277                 }
  278                 printf("};\n");
  279                 printf("extern const struct vnodeop_desc %s_desc;\n", name);
  280         }
  281         # Prototype it.
  282         protoarg = sprintf("int %s(", toupper(name));
  283         protolen = length(protoarg);
  284         printf("%s", protoarg);
  285         for (i=0; i<argc; i++) {
  286                 protoarg = sprintf("%s", argtype[i]);
  287                 if (i < (argc-1)) protoarg = (protoarg ", ");
  288                 arglen = length(protoarg);
  289                 if ((protolen + arglen) > 77) {
  290                         protoarg = ("\n    " protoarg);
  291                         arglen += 4;
  292                         protolen = 0;
  293                 }
  294                 printf("%s", protoarg);
  295                 protolen += arglen;
  296         }
  297         printf(");\n");
  298 }
  299 BEGIN   {
  300         vop_offset = 1; # start at 1, to count the 'default' op
  301 
  302         printf("struct buf;\n");
  303         if (rump) {
  304                 printf("struct flock;\n");
  305                 printf("struct knote;\n");
  306                 printf("struct vm_page;\n");
  307                 printf("struct acl;\n");
  308                 printf("\n#include <sys/acl.h>\n");
  309         }
  310         printf("\n#ifndef _KERNEL\n#include <stdbool.h>\n#endif\n");
  311         if (rump)
  312                 printf("\n");
  313 }
  314 END     {
  315         if (!rump) {
  316                 printf("\n#define VNODE_OPS_COUNT\t%d\n", vop_offset);
  317         }
  318 }
  319 '"$awk_parser" | sed -e "$anal_retentive"
  320 
  321 # End stuff
  322 echo ''
  323 echo "#endif /* !_${SYS}VNODE_IF_H_ */"
  324 }
  325 do_hfile $out_h ''
  326 do_hfile $out_rumph 'rump_'
  327 
  328 do_cfile () {
  329 #
  330 # Redirect stdout to the C file.
  331 #
  332 echo "$0: Creating $1" 1>&2
  333 exec > $1
  334 rump=$2
  335 
  336 # Begin stuff
  337 echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g;s/ $//'
  338 echo ""
  339 echo -n "$copyright"
  340 echo "
  341 #include <sys/cdefs.h>
  342 __KERNEL_RCSID(0, \"\$NetBSD\$\");"
  343 
  344 if [ -z "${rump}" -a ${lockdebug} -ne 0 ] ; then
  345         echo ''
  346         echo '#ifdef _KERNEL_OPT'
  347         echo '#include "opt_vnode_lockdebug.h"'
  348         echo '#endif /* _KERNEL_OPT */'
  349 fi
  350 
  351 echo '
  352 #include <sys/param.h>
  353 #include <sys/mount.h>
  354 #include <sys/buf.h>
  355 #include <sys/fcntl.h>
  356 #include <sys/vnode.h>
  357 #include <sys/lock.h>'
  358 [ -z "${rump}" ] && echo '#include <sys/fstrans.h>'
  359 [ ! -z "${rump}" ] && echo '#include <rump/rumpvnode_if.h>'             \
  360         && echo '#include <rump-sys/kern.h>'
  361 
  362 if [ -z "${rump}" ] ; then
  363         echo "
  364 #include <miscfs/deadfs/deadfs.h>
  365 
  366 enum fst_op { FST_NO, FST_YES, FST_LAZY, FST_TRY };
  367 
  368 static inline int
  369 vop_pre(vnode_t *vp, struct mount **mp, bool *mpsafe, enum fst_op op)
  370 {
  371         int error;
  372 
  373         *mpsafe = (vp->v_vflag & VV_MPSAFE);
  374 
  375         if (!*mpsafe) {
  376                 KERNEL_LOCK(1, curlwp);
  377         }
  378 
  379         if (op == FST_YES || op == FST_LAZY || op == FST_TRY) {
  380                 for (;;) {
  381                         *mp = vp->v_mount;
  382                         if (op == FST_TRY) {
  383                                 error = fstrans_start_nowait(*mp);
  384                                 if (error) {
  385                                         if (!*mpsafe) {
  386                                                 KERNEL_UNLOCK_ONE(curlwp);
  387                                         }
  388                                         return error;
  389                                 }
  390                         } else if (op == FST_LAZY) {
  391                                 fstrans_start_lazy(*mp);
  392                         } else {
  393                                 fstrans_start(*mp);
  394                         }
  395                         if (__predict_true(*mp == vp->v_mount))
  396                                 break;
  397                         fstrans_done(*mp);
  398                 }
  399         } else {
  400                 *mp = vp->v_mount;
  401         }
  402 
  403         return 0;
  404 }
  405 
  406 static inline u_quad_t
  407 vop_pre_get_size(struct vnode *vp)
  408 {
  409         mutex_enter(vp->v_interlock);
  410         KASSERT(vp->v_size != VSIZENOTSET);
  411         u_quad_t rv = (u_quad_t)vp->v_size;
  412         mutex_exit(vp->v_interlock);
  413 
  414         return rv;
  415 }
  416 
  417 /*
  418  * VOP_RMDIR(), VOP_REMOVE(), and VOP_RENAME() need special handling
  419  * because they each drop the caller's references on one or more of
  420  * their arguments.  While there must be an open file descriptor in
  421  * associated with a vnode in order for knotes to be attached to it,
  422  * that status could change during the course of the operation.  So,
  423  * for the vnode arguments that are WILLRELE or WILLPUT, we check
  424  * pre-op if there are registered knotes, take a hold count if so,
  425  * and post-op release the hold after activating any knotes still
  426  * associated with the vnode.
  427  */
  428 
  429 #define VOP_POST_KNOTE(thisvp, e, n)                                    \\
  430 do {                                                                    \\
  431         if (__predict_true((e) == 0)) {                                 \\
  432                 /*                                                      \\
  433                  * VN_KNOTE() does the VN_KEVENT_INTEREST()             \\
  434                  * check for us.                                        \\
  435                  */                                                     \\
  436                 VN_KNOTE((thisvp), (n));                                \\
  437         }                                                               \\
  438 } while (/*CONSTCOND*/0)
  439 
  440 #define VOP_POST_KNOTE_HELD(thisvp, e, n)                               \\
  441 do {                                                                    \\
  442         /*                                                              \\
  443          * We don't perform a VN_KEVENT_INTEREST() check here; it       \\
  444          * was already performed when we did the pre-op work that       \\
  445          * caused the vnode to be held in the first place.              \\
  446          */                                                             \\
  447         mutex_enter((thisvp)->v_interlock);                             \\
  448         if (__predict_true((e) == 0)) {                                 \\
  449                 knote(&(thisvp)->v_klist->vk_klist, (n));               \\
  450         }                                                               \\
  451         holdrelel((thisvp));                                            \\
  452         mutex_exit((thisvp)->v_interlock);                              \\
  453         /*                                                              \\
  454          * thisvp might be gone now!  Don't touch!                      \\
  455          */                                                             \\
  456 } while (/*CONSTCOND*/0)
  457 
  458 #define vop_create_post(ap, e)                                          \\
  459         VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE)
  460 
  461 #define vop_mknod_post(ap, e)                                           \\
  462         VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE)
  463 
  464 #define vop_setattr_pre(ap)                                             \\
  465         u_quad_t osize = 0;                                             \\
  466         long vp_events =                                                \\
  467             VN_KEVENT_INTEREST((ap)->a_vp, NOTE_ATTRIB | NOTE_EXTEND)   \\
  468             ? NOTE_ATTRIB : 0;                                          \\
  469         bool check_extend = false;                                      \\
  470         if (__predict_false(vp_events != 0 &&                           \\
  471             (ap)->a_vap->va_size != VNOVALSIZE)) {                      \\
  472                 check_extend = true;                                    \\
  473                 osize = vop_pre_get_size((ap)->a_vp);                   \\
  474         }
  475 
  476 #define vop_setattr_post(ap, e)                                         \\
  477 do {                                                                    \\
  478         if (__predict_false(vp_events != 0)) {                          \\
  479                 if (__predict_false(check_extend &&                     \\
  480                     (ap)->a_vap->va_size > osize)) {                    \\
  481                         vp_events |= NOTE_EXTEND;                       \\
  482                 }                                                       \\
  483                 VOP_POST_KNOTE((ap)->a_vp, (e), vp_events);             \\
  484         }                                                               \\
  485 } while (/*CONSTCOND*/0)
  486 
  487 #define vop_setacl_post(ap, e)                                          \\
  488         VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_ATTRIB)
  489 
  490 #define vop_link_post(ap, e)                                            \\
  491 do {                                                                    \\
  492         VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE);                   \\
  493         VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_LINK);                     \\
  494 } while (/*CONSTCOND*/0)
  495 
  496 #define vop_mkdir_post(ap, e)                                           \\
  497         VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE | NOTE_LINK)
  498 
  499 #define vop_remove_pre_common(ap)                                       \\
  500         bool post_event_vp =                                            \\
  501             VN_KEVENT_INTEREST((ap)->a_vp, NOTE_DELETE | NOTE_LINK);    \\
  502         if (__predict_false(post_event_vp)) {                           \\
  503                 vhold((ap)->a_vp);                                      \\
  504         }
  505 
  506 #define vop_remove_post_common(ap, e, dn, lc)                           \\
  507 do {                                                                    \\
  508         VOP_POST_KNOTE((ap)->a_dvp, (e), (dn));                         \\
  509         if (__predict_false(post_event_vp)) {                           \\
  510                 VOP_POST_KNOTE_HELD((ap)->a_vp, (e),                    \\
  511                     (lc) ? NOTE_LINK : NOTE_DELETE);                    \\
  512         }                                                               \\
  513 } while (/*CONSTCOND*/0)
  514 
  515 /*
  516  * One could make the argument that VOP_REMOVE() should send NOTE_LINK
  517  * on vp if the resulting link count is not zero, but that's not what
  518  * the documentation says.
  519  *
  520  * We could change this easily by passing ap->ctx_vp_new_nlink to
  521  * vop_remove_post_common().
  522  */
  523 #define vop_remove_pre(ap)                                              \\
  524         vop_remove_pre_common((ap));                                    \\
  525         /*                                                              \\
  526          * We will assume that the file being removed is deleted unless \\
  527          * the file system tells us otherwise by updating vp_new_nlink. \\
  528          */                                                             \\
  529         (ap)->ctx_vp_new_nlink = 0;
  530 
  531 #define vop_remove_post(ap, e)                                          \\
  532         vop_remove_post_common((ap), (e), NOTE_WRITE, 0)
  533 
  534 #define vop_rmdir_pre(ap)                                               \\
  535         vop_remove_pre_common(ap)
  536 
  537 #define vop_rmdir_post(ap, e)                                           \\
  538         vop_remove_post_common((ap), (e), NOTE_WRITE | NOTE_LINK, 0)
  539 
  540 #define vop_symlink_post(ap, e)                                         \\
  541         VOP_POST_KNOTE((ap)->a_dvp, (e), NOTE_WRITE)
  542 
  543 #define vop_open_post(ap, e)                                            \\
  544         VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_OPEN)
  545 
  546 #define vop_close_post(ap, e)                                           \\
  547 do {                                                                    \\
  548         /* See the definition of VN_KNOTE() in <sys/vnode.h>. */        \\
  549         if (__predict_false(VN_KEVENT_INTEREST((ap)->a_vp,              \\
  550             NOTE_CLOSE_WRITE | NOTE_CLOSE) && (e) == 0)) {              \\
  551                 struct vnode *thisvp = (ap)->a_vp;                      \\
  552                 mutex_enter(thisvp->v_interlock);                       \\
  553                 /*                                                      \\
  554                  * Don't send NOTE_CLOSE when closing a vnode that's    \\
  555                  * been reclaimed or otherwise revoked; a NOTE_REVOKE   \\
  556                  * has already been sent, and this close is effectively \\
  557                  * meaningless from the watcher's perspective.          \\
  558                  */                                                     \\
  559                 if (__predict_true(thisvp->v_op != dead_vnodeop_p)) {   \\
  560                         knote(&thisvp->v_klist->vk_klist,               \\
  561                             ((ap)->a_fflag & FWRITE)                    \\
  562                             ? NOTE_CLOSE_WRITE : NOTE_CLOSE);           \\
  563                 }                                                       \\
  564                 mutex_exit(thisvp->v_interlock);                        \\
  565         }                                                               \\
  566 } while (/*CONSTCOND*/0)
  567 
  568 #define vop_read_post(ap, e)                                            \\
  569         VOP_POST_KNOTE((ap)->a_vp, (e), NOTE_READ)
  570 
  571 #define vop_write_pre(ap)                                               \\
  572         off_t ooffset = 0, noffset = 0;                                 \\
  573         u_quad_t osize = 0;                                             \\
  574         long vp_events =                                                \\
  575             VN_KEVENT_INTEREST((ap)->a_vp, NOTE_WRITE | NOTE_EXTEND)    \\
  576             ? NOTE_WRITE : 0;                                           \\
  577         if (__predict_false(vp_events != 0)) {                          \\
  578                 ooffset = (ap)->a_uio->uio_offset;                      \\
  579                 osize = vop_pre_get_size((ap)->a_vp);                   \\
  580         }
  581 
  582 #define vop_write_post(ap, e)                                           \\
  583 do {                                                                    \\
  584         /*                                                              \\
  585          * If any data was written, we'll post an event, even if        \\
  586          * there was an error.                                          \\
  587          */                                                             \\
  588         noffset = (ap)->a_uio->uio_offset;                              \\
  589         if (__predict_false(vp_events != 0 && noffset > ooffset)) {     \\
  590                 if (noffset > osize) {                                  \\
  591                         vp_events |= NOTE_EXTEND;                       \\
  592                 }                                                       \\
  593                 VN_KNOTE((ap)->a_vp, vp_events);                        \\
  594         }                                                               \\
  595 } while (/*CONSTCOND*/0)
  596 
  597 static inline void
  598 vop_post(vnode_t *vp, struct mount *mp, bool mpsafe, enum fst_op op)
  599 {
  600 
  601         if (op == FST_YES || op == FST_LAZY) {
  602                 fstrans_done(mp);
  603         }
  604 
  605         if (!mpsafe) {
  606                 KERNEL_UNLOCK_ONE(curlwp);
  607         }
  608 }
  609 
  610 static inline void
  611 assert_vop_unlocked(vnode_t *vp, const char *str)
  612 {
  613 #if defined(VNODE_LOCKDEBUG)
  614 
  615         if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
  616                 panic(\"%s: %p %d/%d is locked but should not be\",
  617                     str, vp, vp->v_tag, vp->v_type);
  618 #endif
  619 }
  620 
  621 static inline void
  622 assert_vop_locked(vnode_t *vp, const char *str)
  623 {
  624 #if defined(VNODE_LOCKDEBUG)
  625 
  626         if (VOP_ISLOCKED(vp) == LK_NONE)
  627                 panic(\"%s: %p %d/%d is not locked but should be\",
  628                     str, vp, vp->v_tag, vp->v_type);
  629 #endif
  630 }
  631 
  632 static inline void
  633 assert_vop_elocked(vnode_t *vp, const char *str)
  634 {
  635 #if defined(VNODE_LOCKDEBUG)
  636 
  637         if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE)
  638                 panic(\"%s: %p %d/%d is not exclusive locked but should be\",
  639                     str, vp, vp->v_tag, vp->v_type);
  640 #endif
  641 }
  642 
  643 const struct vnodeop_desc vop_default_desc = {"
  644 echo '  0,
  645         "default",
  646         0,
  647         NULL,
  648         VDESC_NO_OFFSET,
  649         VDESC_NO_OFFSET,
  650         VDESC_NO_OFFSET,
  651 };
  652 '
  653 fi
  654 
  655 # Body stuff
  656 sed -e "$sed_prep" $src | $awk -v rump=${rump} -v lockdebug=${lockdebug} '
  657 function do_offset(typematch) {
  658         for (i=0; i<argc; i++) {
  659                 if (argtype[i] == typematch) {
  660                         printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n",
  661                                 args_name, argname[i]);
  662                         return i;
  663                 };
  664         };
  665         print "\tVDESC_NO_OFFSET,";
  666         return -1;
  667 }
  668 
  669 function offsets() {
  670         # Define offsets array
  671         printf("const int %s_vp_offsets[] = {\n", name);
  672         for (i=0; i<argc; i++) {
  673                 if (argtype[i] == "struct vnode *") {
  674                         printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n",
  675                                 args_name, argname[i]);
  676                 }
  677         }
  678         print "\tVDESC_NO_OFFSET";
  679         print "};";
  680         # Define F_desc
  681         printf("const struct vnodeop_desc %s_desc = {\n", name);
  682         # offset
  683         printf ("\t%s_DESCOFFSET,\n", toupper(name));
  684         # printable name
  685         printf ("\t\"%s\",\n", name);
  686         # flags
  687         printf("\t0");
  688         vpnum = 0;
  689         for (i=0; i<argc; i++) {
  690                 if (willrele[i]) {
  691                         if (willrele[i] == 3) {
  692                                 word = "PUT";
  693                         } else {
  694                                 word = "RELE";
  695                         }
  696                         printf(" | VDESC_VP%s_WILL%s", vpnum, word);
  697                 }
  698                 if (argtype[i] == "struct vnode *")
  699                         vpnum++;
  700         }
  701         print ",";
  702         # vp offsets
  703         printf ("\t%s_vp_offsets,\n", name);
  704         # vpp (if any)
  705         do_offset("struct vnode **");
  706         # cred (if any)
  707         do_offset("kauth_cred_t");
  708         # componentname
  709         do_offset("struct componentname *");
  710         printf ("};\n");
  711 }
  712 
  713 function bodyrump() {
  714         printf("{\n\tint error;\n\n");
  715         printf("\trump_schedule();\n");
  716         printf("\terror = %s(", toupper(name));
  717         for (i=0; i<argc; i++) {
  718                 printf("%s", argname[i]);
  719                 if (i < (argc-1)) printf(", ");
  720         }
  721         printf(");\n");
  722         printf("\trump_unschedule();\n\n");
  723         printf("\treturn error;\n}\n");
  724 }
  725 
  726 function bodynorm() {
  727         printf("{\n\tint error;\n\tbool mpsafe;\n\tstruct %s_args a;\n",
  728                 args_name);
  729         printf("\tstruct mount *mp;\n");
  730         printf("\ta.a_desc = VDESC(%s);\n", name);
  731         for (i=0; i<argc; i++) {
  732                 printf("\ta.a_%s = %s;\n", argname[i], argname[i]);
  733         }
  734         if (lockdebug) {
  735                 for (i=0; i<argc; i++) {
  736                         if (lockstate[i] == "")
  737                                 continue;
  738                         printf("\tassert_vop_%s(%s, \"%s: %s\");\n",
  739                             lockstate[i], argname[i], name, argname[i]);
  740                 }
  741         }
  742         # This is done before generic vop_pre() because we want
  743         # to do any setup before beginning an fstrans.
  744         if (do_pre != "")
  745                 printf("\t%s(&a);\n", do_pre);
  746         if (fstrans == "LOCK")
  747                 printf("\terror = vop_pre(%s, &mp, &mpsafe, %s);\n",
  748                         argname[0], "(!(flags & (LK_SHARED|LK_EXCLUSIVE)) ? FST_NO : (flags & LK_NOWAIT ? FST_TRY : FST_YES))");
  749         else if (fstrans == "UNLOCK")
  750                 printf("\terror = vop_pre(%s, &mp, &mpsafe, FST_%s);\n",
  751                         argname[0], "NO");
  752         else
  753                 printf("\terror = vop_pre(%s, &mp, &mpsafe, FST_%s);\n",
  754                         argname[0], fstrans);
  755         printf("\tif (error)\n\t\treturn error;\n");
  756         printf("\terror = (VCALL(%s, VOFFSET(%s), &a));\n",
  757                 argname[0], name);
  758         if (fstrans == "LOCK")
  759                 printf("\tvop_post(%s, mp, mpsafe, %s);\n",
  760                         argname[0], "(flags & (LK_UPGRADE|LK_DOWNGRADE) ? FST_NO : (error ? FST_YES : FST_NO))");
  761         else if (fstrans == "UNLOCK")
  762                 printf("\tvop_post(%s, mp, mpsafe, FST_%s);\n",
  763                         argname[0], "YES");
  764         else
  765                 printf("\tvop_post(%s, mp, mpsafe, FST_%s);\n",
  766                         argname[0], fstrans);
  767         # This is done after generic vop_post() in order to minimize
  768         # time spent with the KERNEL_LOCK held for file systems that
  769         # still require it.
  770         if (do_post != "")
  771                 printf("\t%s(&a, error);\n", do_post);
  772         if (willmake != -1) {
  773                 printf("#ifdef DIAGNOSTIC\n");
  774                 printf("\tif (error == 0)\n"                            \
  775                     "\t\tKASSERT((*%s)->v_size != VSIZENOTSET\n"        \
  776                     "\t\t    && (*%s)->v_writesize != VSIZENOTSET);\n",
  777                     argname[willmake], argname[willmake]);
  778                 printf("#endif /* DIAGNOSTIC */\n");
  779         }
  780         printf("\treturn error;\n}\n");
  781 }
  782 
  783 function doit() {
  784         printf("\n");
  785         if (!rump)
  786                 offsets();
  787 
  788         if (rump)
  789                 extname = "RUMP_" toupper(name);
  790         else
  791                 extname = toupper(name);
  792 
  793         # Define function.
  794         printf("int\n%s(", extname);
  795         for (i=0; i<argc; i++) {
  796                 printf("%s %s", argtype[i], argname[i]);
  797                 if (i < (argc-1)) printf(",\n    ");
  798         }
  799         printf(")\n");
  800 
  801         if (rump)
  802                 bodyrump();
  803         else
  804                 bodynorm();
  805 }
  806 BEGIN   {
  807         # start from 1 (vop_default is at 0)
  808         argc=1;
  809 }
  810 '"$awk_parser" | sed -e "$anal_retentive"
  811 
  812 # End stuff
  813 [ -n "${rump}" ] && return
  814 
  815 # Add the vfs_op_descs array to the C file.
  816 # Begin stuff
  817 echo "
  818 const struct vnodeop_desc * const ${rump}vfs_op_descs[] = {
  819         &${rump}vop_default_desc,       /* MUST BE FIRST */
  820 "
  821 
  822 # Body stuff
  823 sed -e "$sed_prep" $src | $awk -v rump=${rump} '
  824 function doit() {
  825         printf("\t&%s_desc,\n", name);
  826 }
  827 '"$awk_parser"
  828 
  829 # End stuff
  830 echo '  NULL
  831 };'
  832 }
  833 do_cfile $out_c ''
  834 do_cfile $out_rumpc 'rump_'
  835 
  836 exit 0
  837 
  838 # Local Variables:
  839 # tab-width: 4
  840 # End:

Cache object: 22a6c683bd634f7282abaea453467ac1


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