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: vnode_if.sh,v 1.5 1995/09/04 00:20:18 dyson Exp $ 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; 74 75#include <vm/vm.h> 76#include <vm/vm_page.h> 77END_OF_LEADING_COMMENT 78 79# Awk script to take vnode_if.src and turn it into vnode_if.h. 80$AWK ' 81 NF == 0 || $0 ~ "^#" { 82 next; 83 } 84 { 85 # Get the function name. 86 name = $1; 87 uname = toupper(name); 88 89 # Get the function arguments. 90 for (c1 = 0;; ++c1) { 91 if (getline <= 0) 92 exit 93 if ($0 ~ "^};") 94 break; 95 a[c1] = $0; 96 } 97 98 # Print out the vop_F_args structure. 99 printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n", 100 name); 101 for (c2 = 0; c2 < c1; ++c2) { 102 c3 = split(a[c2], t); 103 printf("\t"); 104 if (t[2] ~ "WILLRELE") 105 c4 = 3; 106 else 107 c4 = 2; 108 for (; c4 < c3; ++c4) 109 printf("%s ", t[c4]); 110 beg = match(t[c3], "[^*]"); 111 printf("%sa_%s\n", 112 substr(t[c4], 0, beg - 1), substr(t[c4], beg)); 113 } 114 printf("};\n"); 115 116 # Print out extern declaration. 117 printf("extern struct vnodeop_desc %s_desc;\n", name); 118 119 # Print out prototype. 120 printf("static int %s __P((\n", uname); 121 sep = ",\n"; 122 for (c2 = 0; c2 < c1; ++c2) { 123 if (c2 == c1 - 1) 124 sep = "));\n"; 125 c3 = split(a[c2], t); 126 printf("\t"); 127 if (t[2] ~ "WILLRELE") 128 c4 = 3; 129 else 130 c4 = 2; 131 for (; c4 < c3; ++c4) 132 printf("%s ", t[c4]); 133 beg = match(t[c3], "[^*]"); 134 end = match(t[c3], ";"); 135 printf("%s%s%s", 136 substr(t[c4], 0, beg - 1), 137 substr(t[c4], beg, end - beg), sep); 138 } 139 140 # Print out inline struct. 141 printf("static inline int %s(", uname); 142 sep = ", "; 143 for (c2 = 0; c2 < c1; ++c2) { 144 if (c2 == c1 - 1) 145 sep = ")\n"; 146 c3 = split(a[c2], t); 147 beg = match(t[c3], "[^*]"); 148 end = match(t[c3], ";"); 149 printf("%s%s", substr(t[c3], beg, end - beg), sep); 150 } 151 for (c2 = 0; c2 < c1; ++c2) { 152 c3 = split(a[c2], t); 153 printf("\t"); 154 if (t[2] ~ "WILLRELE") 155 c4 = 3; 156 else 157 c4 = 2; 158 for (; c4 < c3; ++c4) 159 printf("%s ", t[c4]); 160 beg = match(t[c3], "[^*]"); 161 printf("%s%s\n", 162 substr(t[c4], 0, beg - 1), substr(t[c4], beg)); 163 } 164 printf("{\n\tstruct %s_args a;\n\n", name); 165 printf("\ta.a_desc = VDESC(%s);\n", name); 166 for (c2 = 0; c2 < c1; ++c2) { 167 c3 = split(a[c2], t); 168 printf("\t"); 169 beg = match(t[c3], "[^*]"); 170 end = match(t[c3], ";"); 171 printf("a.a_%s = %s\n", 172 substr(t[c3], beg, end - beg), substr(t[c3], beg)); 173 } 174 c1 = split(a[0], t); 175 beg = match(t[c1], "[^*]"); 176 end = match(t[c1], ";"); 177 printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n", 178 substr(t[c1], beg, end - beg), name); 179 }' < $SRC >> $HEADER 180 181# Print out header information for vnode_if.c. 182cat << END_OF_LEADING_COMMENT > $CFILE 183/* 184 * This file is produced automatically. 185 * Do not modify anything in here by hand. 186 * 187 * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 188 */ 189 190#include <sys/param.h> 191#include <sys/mount.h> 192#include <sys/vnode.h> 193#include <vm/vm.h> 194#include <vm/vm_page.h> 195 196struct vnodeop_desc vop_default_desc = { 197 0, 198 "default", 199 0, 200 NULL, 201 VDESC_NO_OFFSET, 202 VDESC_NO_OFFSET, 203 VDESC_NO_OFFSET, 204 VDESC_NO_OFFSET, 205 NULL, 206}; 207 208END_OF_LEADING_COMMENT 209 210# Awk script to take vnode_if.src and turn it into vnode_if.c. 211$AWK 'function kill_surrounding_ws (s) { 212 sub (/^[ \t]*/, "", s); 213 sub (/[ \t]*$/, "", s); 214 return s; 215 } 216 217 function read_args() { 218 numargs = 0; 219 while (getline ln) { 220 if (ln ~ /}/) { 221 break; 222 }; 223 224 # Delete comments, if any. 225 gsub (/\/\*.*\*\//, "", ln); 226 227 # Delete leading/trailing space. 228 ln = kill_surrounding_ws(ln); 229 230 # Pick off direction. 231 if (1 == sub(/^INOUT[ \t]+/, "", ln)) 232 dir = "INOUT"; 233 else if (1 == sub(/^IN[ \t]+/, "", ln)) 234 dir = "IN"; 235 else if (1 == sub(/^OUT[ \t]+/, "", ln)) 236 dir = "OUT"; 237 else 238 bail("No IN/OUT direction for \"" ln "\"."); 239 240 # check for "WILLRELE" 241 if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) { 242 rele = "WILLRELE"; 243 } else { 244 rele = "WONTRELE"; 245 }; 246 247 # kill trailing ; 248 if (1 != sub (/;$/, "", ln)) { 249 bail("Missing end-of-line ; in \"" ln "\"."); 250 }; 251 252 # pick off variable name 253 if (!(i = match(ln, /[A-Za-z0-9_]+$/))) { 254 bail("Missing var name \"a_foo\" in \"" ln "\"."); 255 }; 256 arg = substr (ln, i); 257 # Want to <<substr(ln, i) = "";>>, but nawk cannot. 258 # Hack around this. 259 ln = substr(ln, 1, i-1); 260 261 # what is left must be type 262 # (put clean it up some) 263 type = ln; 264 gsub (/[ \t]+/, " ", type); # condense whitespace 265 type = kill_surrounding_ws(type); 266 267 # (boy this was easier in Perl) 268 269 numargs++; 270 dirs[numargs] = dir; 271 reles[numargs] = rele; 272 types[numargs] = type; 273 args[numargs] = arg; 274 }; 275 } 276 277 function generate_operation_vp_offsets() { 278 printf ("int %s_vp_offsets[] = {\n", name); 279 # as a side effect, figure out the releflags 280 releflags = ""; 281 vpnum = 0; 282 for (i=1; i<=numargs; i++) { 283 if (types[i] == "struct vnode *") { 284 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 285 name, args[i]); 286 if (reles[i] == "WILLRELE") { 287 releflags = releflags "|VDESC_VP" vpnum "_WILLRELE"; 288 }; 289 vpnum++; 290 }; 291 }; 292 sub (/^\|/, "", releflags); 293 print "\tVDESC_NO_OFFSET"; 294 print "};"; 295 } 296 297 function find_arg_with_type (type) { 298 for (i=1; i<=numargs; i++) { 299 if (types[i] == type) { 300 return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")"; 301 }; 302 }; 303 return "VDESC_NO_OFFSET"; 304 } 305 306 function generate_operation_desc() { 307 printf ("struct vnodeop_desc %s_desc = {\n", name); 308 # offset 309 printf ("\t0,\n"); 310 # printable name 311 printf ("\t\"%s\",\n", name); 312 # flags 313 vppwillrele = ""; 314 for (i=1; i<=numargs; i++) { 315 if (types[i] == "struct vnode **" && 316 (reles[i] == "WILLRELE")) { 317 vppwillrele = "|VDESC_VPP_WILLRELE"; 318 }; 319 }; 320 if (releflags == "") { 321 printf ("\t0%s,\n", vppwillrele); 322 } else { 323 printf ("\t%s%s,\n", releflags, vppwillrele); 324 }; 325 # vp offsets 326 printf ("\t%s_vp_offsets,\n", name); 327 # vpp (if any) 328 printf ("\t%s,\n", find_arg_with_type("struct vnode **")); 329 # cred (if any) 330 printf ("\t%s,\n", find_arg_with_type("struct ucred *")); 331 # proc (if any) 332 printf ("\t%s,\n", find_arg_with_type("struct proc *")); 333 # componentname 334 printf ("\t%s,\n", find_arg_with_type("struct componentname *")); 335 # transport layer information 336 printf ("\tNULL,\n};\n"); 337 } 338 339 NF == 0 || $0 ~ "^#" { 340 next; 341 } 342 { 343 # get the function name 344 name = $1; 345 346 # get the function arguments 347 read_args(); 348 349 # Print out the vop_F_vp_offsets structure. This all depends 350 # on naming conventions and nothing else. 351 generate_operation_vp_offsets(); 352 353 # Print out the vnodeop_desc structure. 354 generate_operation_desc(); 355 356 printf "\n"; 357 358 }' < $SRC >> $CFILE 359# THINGS THAT DON'T WORK RIGHT YET. 360# 361# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as 362# arguments. This means that these operations can't function successfully 363# through a bypass routine. 364# 365# Bwrite and strategy will be replaced when the VM page/buffer cache 366# integration happens. 367# 368# To get around this problem for now we handle these ops as special cases. 369 370cat << END_OF_SPECIAL_CASES >> $HEADER 371#include <sys/buf.h> 372struct vop_strategy_args { 373 struct vnodeop_desc *a_desc; 374 struct buf *a_bp; 375}; 376extern struct vnodeop_desc vop_strategy_desc; 377static int VOP_STRATEGY __P(( 378 struct buf *bp)); 379static inline int VOP_STRATEGY(bp) 380 struct buf *bp; 381{ 382 struct vop_strategy_args a; 383 384 a.a_desc = VDESC(vop_strategy); 385 a.a_bp = bp; 386 return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a)); 387} 388 389struct vop_bwrite_args { 390 struct vnodeop_desc *a_desc; 391 struct buf *a_bp; 392}; 393extern struct vnodeop_desc vop_bwrite_desc; 394static int VOP_BWRITE __P(( 395 struct buf *bp)); 396static inline int VOP_BWRITE(bp) 397 struct buf *bp; 398{ 399 struct vop_bwrite_args a; 400 401 a.a_desc = VDESC(vop_bwrite); 402 a.a_bp = bp; 403 return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a)); 404} 405END_OF_SPECIAL_CASES 406 407cat << END_OF_SPECIAL_CASES >> $CFILE 408int vop_strategy_vp_offsets[] = { 409 VDESC_NO_OFFSET 410}; 411struct vnodeop_desc vop_strategy_desc = { 412 0, 413 "vop_strategy", 414 0, 415 vop_strategy_vp_offsets, 416 VDESC_NO_OFFSET, 417 VDESC_NO_OFFSET, 418 VDESC_NO_OFFSET, 419 VDESC_NO_OFFSET, 420 NULL, 421}; 422int vop_bwrite_vp_offsets[] = { 423 VDESC_NO_OFFSET 424}; 425struct vnodeop_desc vop_bwrite_desc = { 426 0, 427 "vop_bwrite", 428 0, 429 vop_bwrite_vp_offsets, 430 VDESC_NO_OFFSET, 431 VDESC_NO_OFFSET, 432 VDESC_NO_OFFSET, 433 VDESC_NO_OFFSET, 434 NULL, 435}; 436END_OF_SPECIAL_CASES 437 438# Add the vfs_op_descs array to the C file. 439$AWK ' 440 BEGIN { 441 printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n"); 442 printf("\t&vop_default_desc, /* MUST BE FIRST */\n"); 443 printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n"); 444 printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n"); 445 } 446 END { 447 printf("\tNULL\n};\n"); 448 } 449 NF == 0 || $0 ~ "^#" { 450 next; 451 } 452 { 453 # Get the function name. 454 printf("\t&%s_desc,\n", $1); 455 456 # Skip the function arguments. 457 for (;;) { 458 if (getline <= 0) 459 exit 460 if ($0 ~ "^};") 461 break; 462 } 463 }' < $SRC >> $CFILE 464 465