1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#!/usr/bin/python
# This script generates the boilerplate versions of most fops and cbks in the
# server. This allows the details of leadership-status checking, sequencing
# between leader and followers (including fan-out), and basic error checking
# to be centralized one place, with per-operation code kept to a minimum.
import sys
import codegen
type_re = "([a-z_0-9]+)"
name_re = "\(\*fop_([a-z0-9]+)_t\)"
full_re = type_re + " *" + name_re
fop_cg = codegen.CodeGenerator()
fop_cg.skip = 2
fop_cg.parse_decls(sys.argv[1],full_re)
fop_cg.load_templates(sys.argv[2])
# Use the multi-template feature to generate multiple callbacks from the same
# parsed declarations.
type_re = "([a-z_0-9]+)"
name_re = "\(\*fop_([a-z0-9]+)_cbk_t\)"
full_re = type_re + " *" + name_re
cbk_cg = codegen.CodeGenerator()
cbk_cg.skip = 5
cbk_cg.parse_decls(sys.argv[1],full_re)
cbk_cg.load_templates(sys.argv[2])
# This is a nasty little trick to handle the case where a generated fop needs
# a set of default arguments for the corresponding callback.
fop_cg.make_defaults = cbk_cg.make_defaults
# We need two types of templates. The first, for pure read operations, just
# needs to do a simple am-i-leader check (augmented to allow dirty reads).
# The second, for pure writes, needs to do fan-out to followers between those
# initial checks and local execution. There are other operations that don't
# fit neatly into either category - e.g. lock ops or fsync - so we'll just have
# to handle those manually. The table thus includes entries only for those we
# can categorize. The special cases, plus any new operations we've never even
# heard of, aren't in there.
#
# Various keywords can be used to define/undefine preprocessor symbols used
# in the templates, on a per-function basis. For example, if the keyword here
# is "fsync" (lowercase word or abbreviation) that will cause NSR_CG_FSYNC
# (prefix plus uppercase version) to be defined above all of the generated code
# for that fop.
fop_table = {
"access": "read",
"create": "write",
"discard": "write",
# "entrylk": "read",
"fallocate": "write",
# "fentrylk": "read",
"fgetxattr": "read",
# "finodelk": "read",
# "flush": "read",
"fremovexattr": "write",
"fsetattr": "write",
"fsetxattr": "write",
"fstat": "read",
# "fsync": "read",
# "fsyncdir": "read",
"ftruncate": "write",
"fxattrop": "write",
"getxattr": "read",
# "inodelk": "read",
"link": "write",
# "lk": "read",
# "lookup": "read",
"mkdir": "write",
"mknod": "write",
"open": "write",
"opendir": "read",
"rchecksum": "read",
"readdir": "read",
"readdirp": "read",
"readlink": "read",
"readv": "read",
"removexattr": "write",
"rename": "write",
"rmdir": "write",
"setattr": "write",
"setxattr": "write",
"stat": "read",
"statfs": "read",
"symlink": "write",
"truncate": "write",
"unlink": "write",
"writev": "write,fsync,queue",
"xattrop": "write",
}
fops_done = []
for x in sorted(fop_cg.decls.keys()):
if x in fop_table.keys():
info = fop_table[x].split(",")
kind = info[0]
flags = info[1:]
if ("fsync" in flags) or ("queue" in flags):
flags.append("need_fd")
for fname in flags:
print "#define NSR_CG_%s" % fname.upper()
cbk_cg.emit(x,kind+"-complete")
fop_cg.emit(x,kind+"-continue")
cbk_cg.emit(x,kind+"-fan-in")
fop_cg.emit(x,kind+"-dispatch")
fop_cg.emit(x,kind+"-fop")
for fname in flags:
print "#undef NSR_CG_%s" % fname.upper()
fops_done.append(x)
else:
print("/* No code emitted for %s */"%x)
print("")
# Just for fun, emit the fops table too.
print("struct xlator_fops fops = {")
for x in fops_done:
print(" .%s = nsr_%s,"%(x,x))
print("};")
|