191511Sobrien#!/usr/bin/awk -f 251681Seivind 3139825Simp#- 41541Srgrimes# Copyright (c) 1992, 1993 51541Srgrimes# The Regents of the University of California. All rights reserved. 61541Srgrimes# 71541Srgrimes# Redistribution and use in source and binary forms, with or without 81541Srgrimes# modification, are permitted provided that the following conditions 91541Srgrimes# are met: 101541Srgrimes# 1. Redistributions of source code must retain the above copyright 111541Srgrimes# notice, this list of conditions and the following disclaimer. 121541Srgrimes# 2. Redistributions in binary form must reproduce the above copyright 131541Srgrimes# notice, this list of conditions and the following disclaimer in the 141541Srgrimes# documentation and/or other materials provided with the distribution. 151541Srgrimes# 4. Neither the name of the University nor the names of its contributors 161541Srgrimes# may be used to endorse or promote products derived from this software 171541Srgrimes# without specific prior written permission. 181541Srgrimes# 191541Srgrimes# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 201541Srgrimes# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211541Srgrimes# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221541Srgrimes# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 231541Srgrimes# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241541Srgrimes# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251541Srgrimes# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261541Srgrimes# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271541Srgrimes# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281541Srgrimes# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 291541Srgrimes# SUCH DAMAGE. 30139825Simp 311541Srgrimes# 321541Srgrimes# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 3350477Speter# $FreeBSD$ 341541Srgrimes# 351541Srgrimes# Script to produce VFS front-end sugar. 361541Srgrimes# 37158936Sdds# usage: vnode_if.awk <srcfile> [-c | -h | -p | -q] 3891511Sobrien# (where <srcfile> is currently /sys/kern/vnode_if.src) 39158936Sdds# The source file must have a .src extension 401541Srgrimes# 411541Srgrimes 4291511Sobrienfunction usage() 4391511Sobrien{ 44138290Sphk print "usage: vnode_if.awk <srcfile> [-c|-h|-p|-q]"; 4591511Sobrien exit 1; 4691511Sobrien} 4762168Salfred 4891511Sobrienfunction die(msg, what) 4991511Sobrien{ 50159083Sdds printf srcfile "(" fnr "): " > "/dev/stderr"; 5191511Sobrien printf msg "\n", what > "/dev/stderr"; 5291511Sobrien exit 1; 5391511Sobrien} 541541Srgrimes 5591511Sobrienfunction t_spc(type) 5691511Sobrien{ 5791511Sobrien # Append a space if the type is not a pointer 5891511Sobrien return (type ~ /\*$/) ? type : type " "; 5991511Sobrien} 6051681Seivind 6191511Sobrien# These are just for convenience ... 6291511Sobrienfunction printc(s) {print s > cfile;} 6391511Sobrienfunction printh(s) {print s > hfile;} 64138290Sphkfunction printp(s) {print s > pfile;} 65138290Sphkfunction printq(s) {print s > qfile;} 6691511Sobrien 67140165Sphkfunction add_debug_code(name, arg, pos, ind) 6891511Sobrien{ 69116614Sse if (arg == "vpp") 70140165Sphk star = "*"; 71140165Sphk else 72140165Sphk star = ""; 73116694Struckman if (lockdata[name, arg, pos] && (lockdata[name, arg, pos] != "-")) { 74140165Sphk printc(ind"ASSERT_VI_UNLOCKED("star"a->a_"arg", \""uname"\");"); 7591511Sobrien # Add assertions for locking 76100919Sjeff if (lockdata[name, arg, pos] == "L") 77140165Sphk printc(ind"ASSERT_VOP_LOCKED(" star "a->a_"arg", \""uname"\");"); 78100919Sjeff else if (lockdata[name, arg, pos] == "U") 79140165Sphk printc(ind"ASSERT_VOP_UNLOCKED(" star "a->a_"arg", \""uname"\");"); 80144907Sjeff else if (lockdata[name, arg, pos] == "E") 81144907Sjeff printc(ind"ASSERT_VOP_ELOCKED(" star "a->a_"arg", \""uname"\");"); 8291511Sobrien else if (0) { 8391511Sobrien # XXX More checks! 8491511Sobrien } 8591511Sobrien } 8651681Seivind} 8751681Seivind 88147198Sssouhlalfunction add_pre(name) 8999482Sjeff{ 9099516Sjeff if (lockdata[name, "pre"]) { 91140165Sphk printc("\t"lockdata[name, "pre"]"(a);"); 9299482Sjeff } 9399482Sjeff} 9499482Sjeff 95147198Sssouhlalfunction add_post(name) 9699482Sjeff{ 9799516Sjeff if (lockdata[name, "post"]) { 98140165Sphk printc("\t"lockdata[name, "post"]"(a, rc);"); 9999482Sjeff } 10099482Sjeff} 10199482Sjeff 10291511Sobrienfunction find_arg_with_type (type) 10391511Sobrien{ 10491511Sobrien for (jj = 0; jj < numargs; jj++) { 10591511Sobrien if (types[jj] == type) { 10691511Sobrien return "VOPARG_OFFSETOF(struct " \ 10791511Sobrien name "_args,a_" args[jj] ")"; 10891511Sobrien } 10991511Sobrien } 1101541Srgrimes 11191511Sobrien return "VDESC_NO_OFFSET"; 11291511Sobrien} 1131541Srgrimes 11491511SobrienBEGIN{ 1151541Srgrimes 11691511Sobrien# Process the command line 11791511Sobrienfor (i = 1; i < ARGC; i++) { 11891511Sobrien arg = ARGV[i]; 119138290Sphk if (arg !~ /^-[chpq]+$/ && arg !~ /\.src$/) 12091511Sobrien usage(); 12191511Sobrien if (arg ~ /^-.*c/) 12291511Sobrien cfile = "vnode_if.c"; 12391511Sobrien if (arg ~ /^-.*h/) 12491511Sobrien hfile = "vnode_if.h"; 125138290Sphk if (arg ~ /^-.*p/) 126138290Sphk pfile = "vnode_if_newproto.h"; 127138290Sphk if (arg ~ /^-.*q/) 128138290Sphk qfile = "vnode_if_typedef.h"; 12991511Sobrien if (arg ~ /\.src$/) 13091511Sobrien srcfile = arg; 13154499Speter} 13291511SobrienARGC = 1; 1331541Srgrimes 134138290Sphkif (!cfile && !hfile && !pfile && !qfile) 13591511Sobrien exit 0; 1361541Srgrimes 13791511Sobrienif (!srcfile) 13891511Sobrien usage(); 1391541Srgrimes 14091511Sobriencommon_head = \ 14191511Sobrien "/*\n" \ 14291511Sobrien " * This file is produced automatically.\n" \ 14391511Sobrien " * Do not modify anything in here by hand.\n" \ 14491511Sobrien " *\n" \ 14591511Sobrien " * Created from $FreeBSD$\n" \ 14691511Sobrien " */\n" \ 14791511Sobrien "\n"; 1481541Srgrimes 149138290Sphkif (pfile) { 150138290Sphk printp(common_head) 151138290Sphk printp("struct vop_vector {") 152138290Sphk printp("\tstruct vop_vector\t*vop_default;") 153138290Sphk printp("\tvop_bypass_t\t*vop_bypass;") 154138290Sphk} 155138290Sphk 156138290Sphkif (qfile) { 157138290Sphk printq(common_head) 158138290Sphk} 159138290Sphk 160138290Sphkif (hfile) { 16191511Sobrien printh(common_head "extern struct vnodeop_desc vop_default_desc;"); 162138290Sphk printh("#include \"vnode_if_typedef.h\"") 163138290Sphk printh("#include \"vnode_if_newproto.h\"") 164138290Sphk} 16562168Salfred 16691511Sobrienif (cfile) { 16791511Sobrien printc(common_head \ 168190518Srwatson "#include \"opt_kdtrace.h\"\n" \ 169190518Srwatson "\n" \ 17091511Sobrien "#include <sys/param.h>\n" \ 171147198Sssouhlal "#include <sys/event.h>\n" \ 172190518Srwatson "#include <sys/kernel.h>\n" \ 173147198Sssouhlal "#include <sys/mount.h>\n" \ 174190518Srwatson "#include <sys/sdt.h>\n" \ 175247116Sjhb "#include <sys/signalvar.h>\n" \ 17696008Sjeff "#include <sys/systm.h>\n" \ 17791511Sobrien "#include <sys/vnode.h>\n" \ 17891511Sobrien "\n" \ 179190518Srwatson "SDT_PROVIDER_DECLARE(vfs);\n" \ 180190518Srwatson "\n" \ 18191511Sobrien "struct vnodeop_desc vop_default_desc = {\n" \ 18291511Sobrien " \"default\",\n" \ 18391511Sobrien " 0,\n" \ 184153400Sdes " (vop_bypass_t *)vop_panic,\n" \ 18591511Sobrien " NULL,\n" \ 18691511Sobrien " VDESC_NO_OFFSET,\n" \ 18791511Sobrien " VDESC_NO_OFFSET,\n" \ 18891511Sobrien " VDESC_NO_OFFSET,\n" \ 18991511Sobrien " VDESC_NO_OFFSET,\n" \ 19091511Sobrien "};\n"); 19191511Sobrien} 1921541Srgrimes 19391511Sobrienwhile ((getline < srcfile) > 0) { 194159083Sdds fnr++; 19591511Sobrien if (NF == 0) 19691511Sobrien continue; 197159082Sdds if ($1 ~ /^%%/) { 198159083Sdds if (NF != 6 || 199231975Strociny $2 !~ /^[a-z_]+$/ || $3 !~ /^[a-z]+$/ || 200159083Sdds $4 !~ /^.$/ || $5 !~ /^.$/ || $6 !~ /^.$/) { 201159083Sdds die("Invalid %s construction", "%%"); 20291511Sobrien continue; 203159083Sdds } 20491511Sobrien lockdata["vop_" $2, $3, "Entry"] = $4; 20591511Sobrien lockdata["vop_" $2, $3, "OK"] = $5; 20691511Sobrien lockdata["vop_" $2, $3, "Error"] = $6; 20791511Sobrien continue; 2081541Srgrimes } 2091541Srgrimes 210159082Sdds if ($1 ~ /^%!/) { 211159083Sdds if (NF != 4 || 212159083Sdds ($3 != "pre" && $3 != "post")) { 213159083Sdds die("Invalid %s construction", "%!"); 21499482Sjeff continue; 215159083Sdds } 21699482Sjeff lockdata["vop_" $2, $3] = $4; 21799482Sjeff continue; 21899482Sjeff } 219159083Sdds if ($1 ~ /^#/) 22099482Sjeff continue; 22199482Sjeff 22291511Sobrien # Get the function name. 22391511Sobrien name = $1; 22491511Sobrien uname = toupper(name); 225103833Sjeff 22691511Sobrien # Get the function arguments. 22791511Sobrien for (numargs = 0; ; ++numargs) { 22891511Sobrien if ((getline < srcfile) <= 0) { 22991511Sobrien die("Unable to read through the arguments for \"%s\"", 23091511Sobrien name); 23191511Sobrien } 232159083Sdds fnr++; 23391511Sobrien if ($1 ~ /^\};/) 23491511Sobrien break; 23551681Seivind 23691511Sobrien # Delete comments, if any. 23791511Sobrien gsub (/\/\*.*\*\//, ""); 23851681Seivind 23991511Sobrien # Condense whitespace and delete leading/trailing space. 24091511Sobrien gsub(/[[:space:]]+/, " "); 24191511Sobrien sub(/^ /, ""); 24291511Sobrien sub(/ $/, ""); 24351681Seivind 24491511Sobrien # Pick off direction. 24591511Sobrien if ($1 != "INOUT" && $1 != "IN" && $1 != "OUT") 24691511Sobrien die("No IN/OUT direction for \"%s\".", $0); 24791511Sobrien dirs[numargs] = $1; 24891511Sobrien sub(/^[A-Z]* /, ""); 2491541Srgrimes 25091511Sobrien if ((reles[numargs] = $1) == "WILLRELE") 25191511Sobrien sub(/^[A-Z]* /, ""); 25291511Sobrien else 25391511Sobrien reles[numargs] = "WONTRELE"; 2541541Srgrimes 25591511Sobrien # kill trailing ; 25691511Sobrien if (sub(/;$/, "") < 1) 25791511Sobrien die("Missing end-of-line ; in \"%s\".", $0); 2581541Srgrimes 25991511Sobrien # pick off variable name 26091511Sobrien if ((argp = match($0, /[A-Za-z0-9_]+$/)) < 1) 26191511Sobrien die("Missing var name \"a_foo\" in \"%s\".", $0); 26291511Sobrien args[numargs] = substr($0, argp); 26391511Sobrien $0 = substr($0, 1, argp - 1); 2641541Srgrimes 26591511Sobrien # what is left must be type 26691511Sobrien # remove trailing space (if any) 26791511Sobrien sub(/ $/, ""); 26891511Sobrien types[numargs] = $0; 26954499Speter } 270244445Sjeff if (numargs > 4) 271244445Sjeff ctrargs = 4; 272103833Sjeff else 273103833Sjeff ctrargs = numargs; 274244765Sgonzo ctrstr = ctrargs "(KTR_VOP, \"VOP\", \"" uname "\", (uintptr_t)a,\n\t "; 275244445Sjeff ctrstr = ctrstr "\"" args[0] ":0x%jX\", (uintptr_t)a->a_" args[0]; 276140165Sphk for (i = 1; i < ctrargs; ++i) 277244445Sjeff ctrstr = ctrstr ", \"" args[i] ":0x%jX\", a->a_" args[i]; 278103833Sjeff ctrstr = ctrstr ");"; 2791541Srgrimes 280138290Sphk if (pfile) { 281138290Sphk printp("\t"name"_t\t*"name";") 282138290Sphk } 283138290Sphk if (qfile) { 284138290Sphk printq("struct "name"_args;") 285138290Sphk printq("typedef int "name"_t(struct "name"_args *);\n") 286138290Sphk } 287138290Sphk 28891511Sobrien if (hfile) { 28991511Sobrien # Print out the vop_F_args structure. 290138789Simp printh("struct "name"_args {\n\tstruct vop_generic_args a_gen;"); 29191511Sobrien for (i = 0; i < numargs; ++i) 29291511Sobrien printh("\t" t_spc(types[i]) "a_" args[i] ";"); 29391511Sobrien printh("};"); 294140165Sphk printh(""); 2951541Srgrimes 29691511Sobrien # Print out extern declaration. 29791511Sobrien printh("extern struct vnodeop_desc " name "_desc;"); 298140165Sphk printh(""); 29991511Sobrien 300140165Sphk # Print out function prototypes. 301140165Sphk printh("int " uname "_AP(struct " name "_args *);"); 302141515Sphk printh("int " uname "_APV(struct vop_vector *vop, struct " name "_args *);"); 303140165Sphk printh(""); 30491511Sobrien printh("static __inline int " uname "("); 30591511Sobrien for (i = 0; i < numargs; ++i) { 30691511Sobrien printh("\t" t_spc(types[i]) args[i] \ 30791511Sobrien (i < numargs - 1 ? "," : ")")); 30851681Seivind } 309140165Sphk printh("{"); 310140165Sphk printh("\tstruct " name "_args a;"); 311140165Sphk printh(""); 312140166Sphk printh("\ta.a_gen.a_desc = &" name "_desc;"); 31391511Sobrien for (i = 0; i < numargs; ++i) 31491511Sobrien printh("\ta.a_" args[i] " = " args[i] ";"); 315141515Sphk printh("\treturn (" uname "_APV("args[0]"->v_op, &a));"); 316100919Sjeff printh("}"); 317140165Sphk 318140165Sphk printh(""); 31951681Seivind } 32051681Seivind 32191511Sobrien if (cfile) { 32291511Sobrien # Print out the vop_F_vp_offsets structure. This all depends 32391511Sobrien # on naming conventions and nothing else. 32491511Sobrien printc("static int " name "_vp_offsets[] = {"); 32591511Sobrien # as a side effect, figure out the releflags 32691511Sobrien releflags = ""; 32791511Sobrien vpnum = 0; 32891511Sobrien for (i = 0; i < numargs; i++) { 32991511Sobrien if (types[i] == "struct vnode *") { 33091511Sobrien printc("\tVOPARG_OFFSETOF(struct " name \ 33191511Sobrien "_args,a_" args[i] "),"); 33291511Sobrien if (reles[i] == "WILLRELE") { 33391511Sobrien releflags = releflags \ 33491511Sobrien "|VDESC_VP" vpnum "_WILLRELE"; 33591511Sobrien } 33691511Sobrien vpnum++; 33791511Sobrien } 33854499Speter } 33954499Speter 34091511Sobrien sub(/^\|/, "", releflags); 34191511Sobrien printc("\tVDESC_NO_OFFSET"); 34291511Sobrien printc("};"); 34351681Seivind 344190518Srwatson printc("\n"); 345260817Savg printc("SDT_PROBE_DEFINE2(vfs, vop, " name ", entry, \"struct vnode *\", \"struct " name "_args *\");\n"); 346260817Savg printc("SDT_PROBE_DEFINE3(vfs, vop, " name ", return, \"struct vnode *\", \"struct " name "_args *\", \"int\");\n"); 347190518Srwatson 348140165Sphk # Print out function. 349140165Sphk printc("\nint\n" uname "_AP(struct " name "_args *a)"); 350140165Sphk printc("{"); 351141515Sphk printc(""); 352141515Sphk printc("\treturn(" uname "_APV(a->a_" args[0] "->v_op, a));"); 353141515Sphk printc("}"); 354141515Sphk printc("\nint\n" uname "_APV(struct vop_vector *vop, struct " name "_args *a)"); 355141515Sphk printc("{"); 356140165Sphk printc("\tint rc;"); 357140165Sphk printc(""); 358141515Sphk printc("\tVNASSERT(a->a_gen.a_desc == &" name "_desc, a->a_" args[0]","); 359141515Sphk printc("\t (\"Wrong a_desc in " name "(%p, %p)\", a->a_" args[0]", a));"); 360140165Sphk printc("\twhile(vop != NULL && \\"); 361140165Sphk printc("\t vop->"name" == NULL && vop->vop_bypass == NULL)") 362140165Sphk printc("\t\tvop = vop->vop_default;") 363141515Sphk printc("\tVNASSERT(vop != NULL, a->a_" args[0]", (\"No "name"(%p, %p)\", a->a_" args[0]", a));") 364289798Savg printc("\tSDT_PROBE2(vfs, vop, " name ", entry, a->a_" args[0] ", a);\n"); 365140165Sphk for (i = 0; i < numargs; ++i) 366140165Sphk add_debug_code(name, args[i], "Entry", "\t"); 367244445Sjeff printc("\tKTR_START" ctrstr); 368147198Sssouhlal add_pre(name); 369247116Sjhb printc("\tVFS_PROLOGUE(a->a_" args[0]"->v_mount);") 370140165Sphk printc("\tif (vop->"name" != NULL)") 371140165Sphk printc("\t\trc = vop->"name"(a);") 372140165Sphk printc("\telse") 373140165Sphk printc("\t\trc = vop->vop_bypass(&a->a_gen);") 374247116Sjhb printc("\tVFS_EPILOGUE(a->a_" args[0]"->v_mount);") 375289798Savg printc("\tSDT_PROBE3(vfs, vop, " name ", return, a->a_" args[0] ", a, rc);\n"); 376140165Sphk printc("\tif (rc == 0) {"); 377140165Sphk for (i = 0; i < numargs; ++i) 378140165Sphk add_debug_code(name, args[i], "OK", "\t\t"); 379140165Sphk printc("\t} else {"); 380140165Sphk for (i = 0; i < numargs; ++i) 381140165Sphk add_debug_code(name, args[i], "Error", "\t\t"); 382140165Sphk printc("\t}"); 383147198Sssouhlal add_post(name); 384244445Sjeff printc("\tKTR_STOP" ctrstr); 385140165Sphk printc("\treturn (rc);"); 386140165Sphk printc("}\n"); 387140165Sphk 38891511Sobrien # Print out the vnodeop_desc structure. 38991511Sobrien printc("struct vnodeop_desc " name "_desc = {"); 39091511Sobrien # printable name 39191511Sobrien printc("\t\"" name "\","); 39291511Sobrien # flags 39391511Sobrien vppwillrele = ""; 39491511Sobrien for (i = 0; i < numargs; i++) { 39591511Sobrien if (types[i] == "struct vnode **" && \ 39691511Sobrien reles[i] == "WILLRELE") { 39791511Sobrien vppwillrele = "|VDESC_VPP_WILLRELE"; 39891511Sobrien } 39991511Sobrien } 40051681Seivind 40191511Sobrien if (!releflags) 40291511Sobrien releflags = "0"; 40391511Sobrien printc("\t" releflags vppwillrele ","); 40451681Seivind 405140165Sphk # function to call 406153400Sdes printc("\t(vop_bypass_t *)" uname "_AP,"); 40791511Sobrien # vp offsets 40891511Sobrien printc("\t" name "_vp_offsets,"); 40991511Sobrien # vpp (if any) 41091511Sobrien printc("\t" find_arg_with_type("struct vnode **") ","); 41191511Sobrien # cred (if any) 41291511Sobrien printc("\t" find_arg_with_type("struct ucred *") ","); 41391511Sobrien # thread (if any) 41491511Sobrien printc("\t" find_arg_with_type("struct thread *") ","); 41591511Sobrien # componentname 41691511Sobrien printc("\t" find_arg_with_type("struct componentname *") ","); 41791511Sobrien # transport layer information 418153397Sdes printc("};\n"); 41954499Speter } 42051681Seivind} 42154499Speter 422138290Sphkif (pfile) 423138290Sphk printp("};") 424138290Sphk 42591511Sobrienif (hfile) 42691511Sobrien close(hfile); 42791511Sobrienif (cfile) 42891511Sobrien close(cfile); 429138290Sphkif (pfile) 430138290Sphk close(pfile); 43191511Sobrienclose(srcfile); 43251681Seivind 43351681Seivindexit 0; 43451681Seivind 43551681Seivind} 436