1#!/bin/sh - 2# 3# Copyright (c) 1992, 1993 4# The Regents of the University of California. All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 3. All advertising materials mentioning features or use of this software 15# must display the following acknowledgement: 16# This product includes software developed by the University of 17# California, Berkeley and its contributors. 18# 4. Neither the name of the University nor the names of its contributors 19# may be used to endorse or promote products derived from this software 20# without specific prior written permission. 21# 22# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32# SUCH DAMAGE. 33# 34# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 35# $Id$ 36# 37 38# Script to produce VFS front-end sugar. 39# 40# usage: vnode_if.sh srcfile 41# (where srcfile is currently /sys/kern/vnode_if.src) 42# 43# These awk scripts are not particularly well written, specifically they 44# don't use arrays well and figure out the same information repeatedly. 45# Please rewrite them if you actually understand how to use awk. Note, 46# they use nawk extensions and gawk's toupper. 47 48if [ $# -ne 1 ] ; then 49 echo 'usage: vnode_if.sh srcfile' 50 exit 1 51fi 52 53# Name of the source file. 54SRC=$1 55 56# Names of the created files. 57CFILE=vnode_if.c 58HEADER=vnode_if.h 59 60# Awk program (must support nawk extensions and gawk's "toupper") 61# Use "awk" at Berkeley, "gawk" elsewhere. 62AWK=awk 63 64# Print out header information for vnode_if.h. 65cat << END_OF_LEADING_COMMENT > $HEADER 66/* 67 * This file is produced automatically. 68 * Do not modify anything in here by hand. 69 * 70 * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 71 */ 72 73extern struct vnodeop_desc vop_default_desc; 74END_OF_LEADING_COMMENT 75 76# Awk script to take vnode_if.src and turn it into vnode_if.h. 77$AWK ' 78 NF == 0 || $0 ~ "^#" { 79 next; 80 } 81 { 82 # Get the function name. 83 name = $1; 84 uname = toupper(name); 85 86 # Get the function arguments. 87 for (c1 = 0;; ++c1) { 88 if (getline <= 0) 89 exit 90 if ($0 ~ "^};") 91 break; 92 a[c1] = $0; 93 } 94 95 # Print out the vop_F_args structure. 96 printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n", 97 name); 98 for (c2 = 0; c2 < c1; ++c2) { 99 c3 = split(a[c2], t); 100 printf("\t"); 101 if (t[2] ~ "WILLRELE") 102 c4 = 3; 103 else 104 c4 = 2; 105 for (; c4 < c3; ++c4) 106 printf("%s ", t[c4]); 107 beg = match(t[c3], "[^*]"); 108 printf("%sa_%s\n", 109 substr(t[c4], 0, beg - 1), substr(t[c4], beg)); 110 } 111 printf("};\n"); 112 113 # Print out extern declaration. 114 printf("extern struct vnodeop_desc %s_desc;\n", name); 115 116 # Print out prototype. 117 printf("static int %s __P((\n", uname); 118 sep = ",\n"; 119 for (c2 = 0; c2 < c1; ++c2) { 120 if (c2 == c1 - 1) 121 sep = "));\n"; 122 c3 = split(a[c2], t); 123 printf("\t"); 124 if (t[2] ~ "WILLRELE") 125 c4 = 3; 126 else 127 c4 = 2; 128 for (; c4 < c3; ++c4) 129 printf("%s ", t[c4]); 130 beg = match(t[c3], "[^*]"); 131 end = match(t[c3], ";"); 132 printf("%s%s%s", 133 substr(t[c4], 0, beg - 1), 134 substr(t[c4], beg, end - beg), sep); 135 } 136 137 # Print out inline struct. 138 printf("static inline int %s(", uname); 139 sep = ", "; 140 for (c2 = 0; c2 < c1; ++c2) { 141 if (c2 == c1 - 1) 142 sep = ")\n"; 143 c3 = split(a[c2], t); 144 beg = match(t[c3], "[^*]"); 145 end = match(t[c3], ";"); 146 printf("%s%s", substr(t[c3], beg, end - beg), sep); 147 } 148 for (c2 = 0; c2 < c1; ++c2) { 149 c3 = split(a[c2], t); 150 printf("\t"); 151 if (t[2] ~ "WILLRELE") 152 c4 = 3; 153 else 154 c4 = 2; 155 for (; c4 < c3; ++c4) 156 printf("%s ", t[c4]); 157 beg = match(t[c3], "[^*]"); 158 printf("%s%s\n", 159 substr(t[c4], 0, beg - 1), substr(t[c4], beg)); 160 } 161 printf("{\n\tstruct %s_args a;\n\n", name); 162 printf("\ta.a_desc = VDESC(%s);\n", name); 163 for (c2 = 0; c2 < c1; ++c2) { 164 c3 = split(a[c2], t); 165 printf("\t"); 166 beg = match(t[c3], "[^*]"); 167 end = match(t[c3], ";"); 168 printf("a.a_%s = %s\n", 169 substr(t[c3], beg, end - beg), substr(t[c3], beg)); 170 } 171 c1 = split(a[0], t); 172 beg = match(t[c1], "[^*]"); 173 end = match(t[c1], ";"); 174 printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n", 175 substr(t[c1], beg, end - beg), name); 176 }' < $SRC >> $HEADER 177 178# Print out header information for vnode_if.c. 179cat << END_OF_LEADING_COMMENT > $CFILE 180/* 181 * This file is produced automatically. 182 * Do not modify anything in here by hand. 183 * 184 * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 185 */ 186 187#include <sys/param.h> 188#include <sys/mount.h> 189#include <sys/vnode.h> 190 191struct vnodeop_desc vop_default_desc = { 192 0, 193 "default", 194 0, 195 NULL, 196 VDESC_NO_OFFSET, 197 VDESC_NO_OFFSET, 198 VDESC_NO_OFFSET, 199 VDESC_NO_OFFSET, 200 NULL, 201}; 202 203END_OF_LEADING_COMMENT 204 205# Awk script to take vnode_if.src and turn it into vnode_if.c. 206$AWK 'function kill_surrounding_ws (s) { 207 sub (/^[ \t]*/, "", s); 208 sub (/[ \t]*$/, "", s); 209 return s; 210 } 211 212 function read_args() { 213 numargs = 0; 214 while (getline ln) { 215 if (ln ~ /}/) { 216 break; 217 }; 218 219 # Delete comments, if any. 220 gsub (/\/\*.*\*\//, "", ln); 221 222 # Delete leading/trailing space. 223 ln = kill_surrounding_ws(ln); 224 225 # Pick off direction. 226 if (1 == sub(/^INOUT[ \t]+/, "", ln)) 227 dir = "INOUT"; 228 else if (1 == sub(/^IN[ \t]+/, "", ln)) 229 dir = "IN"; 230 else if (1 == sub(/^OUT[ \t]+/, "", ln)) 231 dir = "OUT"; 232 else 233 bail("No IN/OUT direction for \"" ln "\"."); 234 235 # check for "WILLRELE" 236 if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) { 237 rele = "WILLRELE"; 238 } else { 239 rele = "WONTRELE"; 240 }; 241 242 # kill trailing ; 243 if (1 != sub (/;$/, "", ln)) { 244 bail("Missing end-of-line ; in \"" ln "\"."); 245 }; 246 247 # pick off variable name 248 if (!(i = match(ln, /[A-Za-z0-9_]+$/))) { 249 bail("Missing var name \"a_foo\" in \"" ln "\"."); 250 }; 251 arg = substr (ln, i); 252 # Want to <<substr(ln, i) = "";>>, but nawk cannot. 253 # Hack around this. 254 ln = substr(ln, 1, i-1); 255 256 # what is left must be type 257 # (put clean it up some) 258 type = ln; 259 gsub (/[ \t]+/, " ", type); # condense whitespace 260 type = kill_surrounding_ws(type); 261 262 # (boy this was easier in Perl) 263 264 numargs++; 265 dirs[numargs] = dir; 266 reles[numargs] = rele; 267 types[numargs] = type; 268 args[numargs] = arg; 269 }; 270 } 271 272 function generate_operation_vp_offsets() { 273 printf ("static int %s_vp_offsets[] = {\n", name); 274 # as a side effect, figure out the releflags 275 releflags = ""; 276 vpnum = 0; 277 for (i=1; i<=numargs; i++) { 278 if (types[i] == "struct vnode *") { 279 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 280 name, args[i]); 281 if (reles[i] == "WILLRELE") { 282 releflags = releflags "|VDESC_VP" vpnum "_WILLRELE"; 283 }; 284 vpnum++; 285 }; 286 }; 287 sub (/^\|/, "", releflags); 288 print "\tVDESC_NO_OFFSET"; 289 print "};"; 290 } 291 292 function find_arg_with_type (type) { 293 for (i=1; i<=numargs; i++) { 294 if (types[i] == type) { 295 return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")"; 296 }; 297 }; 298 return "VDESC_NO_OFFSET"; 299 } 300 301 function generate_operation_desc() { 302 printf ("struct vnodeop_desc %s_desc = {\n", name); 303 # offset 304 printf ("\t0,\n"); 305 # printable name 306 printf ("\t\"%s\",\n", name); 307 # flags 308 vppwillrele = ""; 309 for (i=1; i<=numargs; i++) { 310 if (types[i] == "struct vnode **" && 311 (reles[i] == "WILLRELE")) { 312 vppwillrele = "|VDESC_VPP_WILLRELE"; 313 }; 314 }; 315 if (releflags == "") { 316 printf ("\t0%s,\n", vppwillrele); 317 } else { 318 printf ("\t%s%s,\n", releflags, vppwillrele); 319 }; 320 # vp offsets 321 printf ("\t%s_vp_offsets,\n", name); 322 # vpp (if any) 323 printf ("\t%s,\n", find_arg_with_type("struct vnode **")); 324 # cred (if any) 325 printf ("\t%s,\n", find_arg_with_type("struct ucred *")); 326 # proc (if any) 327 printf ("\t%s,\n", find_arg_with_type("struct proc *")); 328 # componentname 329 printf ("\t%s,\n", find_arg_with_type("struct componentname *")); 330 # transport layer information 331 printf ("\tNULL,\n};\n"); 332 } 333 334 NF == 0 || $0 ~ "^#" { 335 next; 336 } 337 { 338 # get the function name 339 name = $1; 340 341 # get the function arguments 342 read_args(); 343 344 # Print out the vop_F_vp_offsets structure. This all depends 345 # on naming conventions and nothing else. 346 generate_operation_vp_offsets(); 347 348 # Print out the vnodeop_desc structure. 349 generate_operation_desc(); 350 351 printf "\n"; 352 353 }' < $SRC >> $CFILE 354# THINGS THAT DON'T WORK RIGHT YET. 355# 356# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as 357# arguments. This means that these operations can't function successfully 358# through a bypass routine. 359# 360# Bwrite and strategy will be replaced when the VM page/buffer cache 361# integration happens. 362# 363# To get around this problem for now we handle these ops as special cases. 364 365cat << END_OF_SPECIAL_CASES >> $HEADER 366#include <sys/buf.h> 367struct vop_strategy_args { 368 struct vnodeop_desc *a_desc; 369 struct buf *a_bp; 370}; 371extern struct vnodeop_desc vop_strategy_desc; 372static int VOP_STRATEGY __P(( 373 struct buf *bp)); 374static inline int VOP_STRATEGY(bp) 375 struct buf *bp; 376{ 377 struct vop_strategy_args a; 378 379 a.a_desc = VDESC(vop_strategy); 380 a.a_bp = bp; 381 return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a)); 382} 383 384struct vop_bwrite_args { 385 struct vnodeop_desc *a_desc; 386 struct buf *a_bp; 387}; 388extern struct vnodeop_desc vop_bwrite_desc; 389static int VOP_BWRITE __P(( 390 struct buf *bp)); 391static inline int VOP_BWRITE(bp) 392 struct buf *bp; 393{ 394 struct vop_bwrite_args a; 395 396 a.a_desc = VDESC(vop_bwrite); 397 a.a_bp = bp; 398 return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a)); 399} 400END_OF_SPECIAL_CASES 401 402cat << END_OF_SPECIAL_CASES >> $CFILE 403static int vop_strategy_vp_offsets[] = { 404 VDESC_NO_OFFSET 405}; 406struct vnodeop_desc vop_strategy_desc = { 407 0, 408 "vop_strategy", 409 0, 410 vop_strategy_vp_offsets, 411 VDESC_NO_OFFSET, 412 VDESC_NO_OFFSET, 413 VDESC_NO_OFFSET, 414 VDESC_NO_OFFSET, 415 NULL, 416}; 417static int vop_bwrite_vp_offsets[] = { 418 VDESC_NO_OFFSET 419}; 420struct vnodeop_desc vop_bwrite_desc = { 421 0, 422 "vop_bwrite", 423 0, 424 vop_bwrite_vp_offsets, 425 VDESC_NO_OFFSET, 426 VDESC_NO_OFFSET, 427 VDESC_NO_OFFSET, 428 VDESC_NO_OFFSET, 429 NULL, 430}; 431END_OF_SPECIAL_CASES 432 433# Add the vfs_op_descs array to the C file. 434$AWK ' 435 BEGIN { 436 printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n"); 437 printf("\t&vop_default_desc, /* MUST BE FIRST */\n"); 438 printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n"); 439 printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n"); 440 } 441 END { 442 printf("\tNULL\n};\n"); 443 } 444 NF == 0 || $0 ~ "^#" { 445 next; 446 } 447 { 448 # Get the function name. 449 printf("\t&%s_desc,\n", $1); 450 451 # Skip the function arguments. 452 for (;;) { 453 if (getline <= 0) 454 exit 455 if ($0 ~ "^};") 456 break; 457 } 458 }' < $SRC >> $CFILE 459 460