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