Compare commits

...

33 Commits

Author SHA1 Message Date
Anna Schumaker 2022b22180 xfstests.zsh: Various Updates
* Use $COLORS from common.zsh
* Add a --options option to pass generic NFS mount options
* Add the --no-scratch option to run tests without a scratch mount
* Add the --no-server-access option for testing against somebody else's
  server
* Remove the --nconnect and --rwsize options
* Run tcp and rdma tests sequentially instead of in parallel
* Add xfstestsdb support
* Clean up colors/xfstests.py to fix flake8 style errors
* Colorize xfstestsdb xunit output

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-20 14:04:50 -04:00
Anna Schumaker b07b1c2a52 unlock-sqlite-db.zsh: Add script for fixing locked database files
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 15:09:37 -04:00
Anna Schumaker 03255bc333 pull-request.sh: Various Updates
* We are on Linux v6.* now
* Add a subject line template
* Fix the $new tag variable

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 14:56:04 -04:00
Anna Schumaker b2432c671e submit-patches.zsh: Various updates
* Add an option to send to Linus
* Remove extra TO= lines

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 14:54:17 -04:00
Anna Schumaker 8cc4c23e71 read_plus.zsh: Various Updates
* Clean up colors/read_plus.py to match flake8 style guidelines
* Add --dmesg, --srvdmesg, and --no-server-vmtouch options
* Use $COLORS from common.zsh
* Accept a specific filename to test as a command line argument
* Add tests for 3, 5, 6, and 7 page segments

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 14:44:10 -04:00
Anna Schumaker 3e0f52b4e4 install-scripts.zsh: Various Updates
* Use $BIN from common.zsh
* Fixes for colorful output
* Install scripts to .local/bin on the remote machine
* Point setup.zsh at .local/bin instead of .bin
* Run setup/testdirs.zsh with the -e flag

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 13:50:02 -04:00
Anna Schumaker c7aad8e77c syncmusic.sh: Fix source path for the new synology device
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 13:25:23 -04:00
Anna Schumaker 0b9af1b0ff backup.sh: Fix backup path for the new synology device
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 13:24:45 -04:00
Anna Schumaker 078d6e126e vm.zsh: Various Updates
* Improve the exit trap to make sure child processes are stopped
* wait $(jobs -pr) is the same thing as wait with no options

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 13:17:40 -04:00
Anna Schumaker fef564a570 rping.zsh: Various Updates
* Use $COLORS from common.zsh
* Fix colorful output when run from a different script

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 12:02:47 -04:00
Anna Schumaker e4434babcb rdma.zsh: Various Updates
* Use $COLORS from common.zsh
* Fix colored output when run from another script

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 12:01:58 -04:00
Anna Schumaker c843549aa5 deploykernel.zsh: Various Updates
* Add options for cross compiling
* Put the resulting package in a subdirectory to keep the toplevel clean
* Fix color output
* Use $COLORS from common.zsh

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 11:53:10 -04:00
Anna Schumaker 2e9699a52e deploypkg.zsh: Various Updates
* Clean up colors/pacman.py for colorful output
* Fixes for the .local/bin move
* Use the $COLORS and $BIN variables from common.zsh

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 11:45:58 -04:00
Anna Schumaker 70dfceccef makekconfig.py: Various Updates
* Python flake8 style fixes
* Update for the .local/bin change

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-19 11:42:34 -04:00
Anna Schumaker 941308e246 makelinux.zsh: Various Updates
* Fixes to color output
* Added an option to cross compile for i686
* Use the new $COLORS variable for the location of the colors script

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-18 16:18:32 -04:00
Anna Schumaker 2373f06ea7 cthon.zsh: Various Updates
* Point $BIN to $HOME/.local/bin
* Create $COLORS pointing to $BIN/colors
* Use the zsh built-in _libvirt function for completion
* Add a --no-server-access option for testing against somebody else's
  server
* Add a generic --options option, replacing --nconnect and --rwsize but
  allowing for any NFS mount option to be passed instead
* Run RDMA tests after TCP instead of in parallel

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-07-18 16:04:37 -04:00
Anna Schumaker d29b73180f reporter: updates for xfstests xunit generation changes
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-04-17 13:12:51 -04:00
Anna Schumaker d080c04a5d makelinux.zsh: Add compiler selection options
I add an easy way to select between gcc and clang. Additionally, I add
an option to cross-compile for arm64 architectures.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2023-04-04 11:14:50 -04:00
Anna Schumaker 87d2a308c3 xfstests.zsh: Make -g GROUP an option to the script
So we can add tab completion and set a default group when one isn't
passed in.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-25 15:07:04 -04:00
Anna Schumaker 4025aaa0bd colors/xfstests.py: Fix splitting kernel PREEMPT line
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-25 15:05:55 -04:00
Anna Schumaker 061d076ee9 xfstests.zsh: Add a --rwsize option
For setting the rsize and wsize used by the tests

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-24 13:14:13 -04:00
Anna Schumaker d770421063 cthon.zsh: Add an --rwsize option
For setting rsize and wsize for the mount to test

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-24 13:13:41 -04:00
Anna Schumaker 1c3372e3a5 cthon.zsh: Don't return 0 if one of the tests fails
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-23 12:29:51 -04:00
Anna Schumaker 0fed27b109 submit-patches.zsh: Greatly improve the script
Take a command line option for who to send to, rather than relying on
having the proper variable set or commented out. Also, add some tab
completion.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-16 17:02:29 -04:00
Anna Schumaker 5e1664d88a cthon.zsh: Rewrite test
The runcthon script isn't the most straightforward for passing arbitrary
options or running with a specific NFS version. Deal with this by
writing our own version that does what we need it to do.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-05-16 16:53:21 -04:00
Anna Schumaker 600fd846dc common.zsh: Add automatic version verification
And expand "-v 4" to run all NFS v4 minorversions

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-26 10:56:09 -04:00
Anna Schumaker 3428879918 Move setup-* and run-* scripts into subdirectories
The common prefixes in these scripts indicate that they should really be
in directories and not the toplevel. I also provide a helper script in
$BIN to assist in calling them on the target VMs

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-26 10:33:01 -04:00
Anna Schumaker a2453af9cc common.zsh: Move some common test functions into common.zsh
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-25 15:27:36 -04:00
Anna Schumaker f757dec0ab common.zsh: Pull out common test config into a shared file
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-25 15:27:15 -04:00
Anna Schumaker 59d2891198 Add test script for nfstest read plus
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-22 12:30:44 -04:00
Anna Schumaker dd97c7079b read_plus: Add script for testing the READ_PLUS operation
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-18 11:27:52 -04:00
Anna Schumaker a6d46ff0e1 cthon: Add arguments for printing client and server dmesg log
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-18 11:24:50 -04:00
Anna Schumaker cbcc5ba269 cthon: Have colors script exit with the proper exit code
Otherwise, the script will always return success and pipelines using
cthon.zsh won't work properly

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
2022-04-18 11:23:48 -04:00
41 changed files with 1006 additions and 250 deletions

View File

@ -24,7 +24,7 @@ SERVER=cheesecake
# Path where the backup will be placed # Path where the backup will be placed
# Note that this is on the client, using autofs # Note that this is on the client, using autofs
BACKUP_DIRECTORY=/net/cheesecake/srv/Backups/`hostname -f` BACKUP_DIRECTORY=/net/cheesecake/backups/`hostname -f`
# Path on this machine where output should be written # Path on this machine where output should be written
LOG=/tmp/backup.log LOG=/tmp/backup.log
@ -48,5 +48,5 @@ if [ $? != 0 ]; then
fi fi
rsync -axvh --inplace --delete --delete-excluded --exclude-from=$EXCLUDE $BACKUP $BACKUP_DIRECTORY >> $LOG rsync -axvhz --inplace --delete-delay --delete-excluded --exclude-from=$EXCLUDE $BACKUP $BACKUP_DIRECTORY >> $LOG
notify-send "Backup finished!" notify-send "Backup finished!"

View File

@ -5,6 +5,7 @@ import termcolor
colors = { "b" : "blue", "g" : "green", "s" : "cyan", "l" : "yellow" } colors = { "b" : "blue", "g" : "green", "s" : "cyan", "l" : "yellow" }
last = "white" last = "white"
newline = False newline = False
status=0
text = "" text = ""
def print_text(color, attr=None): def print_text(color, attr=None):
@ -20,16 +21,19 @@ while c := sys.stdin.read(1):
text = "\n" + text if newline else text text = "\n" + text if newline else text
newline = False newline = False
print_text("red", "bold") print_text("red", "bold")
status=1
elif match := re.match("^./server -([bgsl]) .*?\n$", text): elif match := re.match("^./server -([bgsl]) .*?\n$", text):
print_text(colors[match.group(1)], None) print_text(colors[match.group(1)], None)
elif match := re.match("^Waiting for '([bgsl])' to finish...", text): elif match := re.match("^Waiting for '\-([bgsl])' to finish ... ", text):
last = colors[match.group(1)] last = colors[match.group(1)]
newline = True newline = True
print_text(last, "bold") print_text(last, "bold")
elif match := re.match("^ Done: .*?\n$", text): elif match := re.match("^Done: .*?\n$", text):
print_text(last, "bold") print_text(last, "bold")
newline = False newline = False
elif c == "\n": elif c == "\n":
if len(text) > 1: if len(text) > 1:
print_text("white", "bold") print_text("white", "bold")
text = "" text = ""
sys.exit(status)

View File

@ -21,15 +21,19 @@ add_color_attr("DESCEND", "white", "dark")
add_color_attr("objtool", "yellow", "dark", "bold") add_color_attr("objtool", "yellow", "dark", "bold")
add_color_attr("LD", "yellow") add_color_attr("LD", "yellow")
for line in sys.stdin: text = ""
if line[0] == "#": while c := sys.stdin.read(1):
termcolor.cprint(line, "blue", attrs=["dark", "bold"], end="") text += c
else: if text[0] == "#":
for part in re.split(r'(\s+)', line): if re.match("^#(.*?)\n", text):
if "/" in part or "(#" in part or os.path.exists(part): termcolor.cprint(text, "blue", attrs=["dark", "bold"], end="")
color = "magenta" if re.match("module", part, re.I) else "white" text = ""
attrs = ["bold"] elif c in (" ", "\n"):
else: if "/" in text or "(#" in text or os.path.exists(text):
color = make_colors.get(part, "green") color = "magenta" if re.match("module", text, re.I) else "white"
attrs = make_attrs.get(part, []) attrs = ["bold"]
termcolor.cprint(part, color, attrs=attrs, end="") else:
color = make_colors.get(text.strip(), "green")
attrs = make_attrs.get(text.strip(), [])
termcolor.cprint(text, color, attrs=attrs, end="")
text = ""

View File

@ -1,17 +1,12 @@
#!/usr/bin/python
"""Add color and machine tags to remote pacman output."""
import termcolor import termcolor
import re import re
import sys import sys
prefix = sys.argv[1] if len(sys.argv) > 1 else None prefix = sys.argv[1] if len(sys.argv) > 1 else None
pacman_colors = dict() pacman_colors = {"==>": "green", "->": "blue"}
pacman_attrs = dict()
def add_color_attr(field, color, *attrs):
pacman_colors[field] = color
pacman_attrs[field] = attrs
add_color_attr("==>", "green", "bold")
add_color_attr("->", "blue", "bold")
for line in sys.stdin: for line in sys.stdin:
if prefix: if prefix:
@ -19,8 +14,7 @@ for line in sys.stdin:
if "==>" in line or "->" in line: if "==>" in line or "->" in line:
for part in re.split(r'(\s+)', line): for part in re.split(r'(\s+)', line):
color = pacman_colors.get(part, "white") color = pacman_colors.get(part, "white")
attrs = pacman_attrs.get(part, ["bold"])
termcolor.cprint(part, color, attrs=attrs, end="") termcolor.cprint(part, color, attrs=["bold"], end="")
else: else:
print(line, end="") print(line, end="")

107
colors/read_plus.py Normal file
View File

@ -0,0 +1,107 @@
"""Colorize read_plus.zsh output."""
import sys
import re
import termcolor
SIZE = sys.argv[1]
FILE = open(sys.argv[2], 'a') if len(sys.argv) >= 3 else None
COLORS = {"data": "red", "hole": "green", "d": "cyan", "h": "yellow"}
def write_log(text: str, color: str = None,
attrs: list = [], end: str = "") -> None:
"""Print a single formatted string to the screen and possibly a file."""
if FILE:
FILE.write(text + end)
termcolor.cprint(text, color=color, attrs=attrs, end=end)
def print_allocation(prefix: str, name: str,
filetype: str, extra: str) -> None:
"""Format and print file allocation information."""
write_log(prefix, color="white", attrs=["dark"])
write_log(name, color=COLORS[filetype], attrs=["bold"])
write_log(extra, color="white", attrs=["dark"])
def print_allocation_done(done: str, time: str, end: str) -> None:
"""Format and print the time to complete file allocation."""
write_log(done, color="white", attrs=["dark"])
write_log(time, color="blue", attrs=["bold"])
write_log(end, color="white", attrs=["dark"])
def print_reading(prefix: str, name: str,
precache: str, cached: str, postcache: str) -> None:
"""Format and print which file we are currently reading."""
match cached:
case "uncached": ccolor = "yellow"
case "cached": ccolor = "green"
case "unknown": ccolor = "grey"
case _: ccolor = "white"
write_log(prefix, color="white", attrs=["dark"])
write_log(name, color=COLORS[filetype], attrs=["bold"])
write_log(precache, color="white", attrs=["dark"])
write_log(cached, color=ccolor, attrs=["bold"])
write_log(postcache, color="white", attrs=["dark"])
write_log(" ...", color="white", attrs=["dark"])
def print_stats_1(walltime: str, speed: str) -> None:
"""Format and print the transfer time and rate information."""
write_log(" ")
write_log(walltime, color="blue", attrs=["bold"])
write_log(", ", color="white", attrs=["dark"])
write_log(speed, color="green", attrs=["bold"])
write_log(", ", color="white", attrs=["dark"])
def print_stats_2(kerntime: str, kernunits: str, cpu: str) -> None:
"""Format and print time spent in the kernel and cpu usage."""
write_log(kerntime, color="cyan", attrs=["bold"], end=" ")
write_log(kernunits, color="cyan", attrs=["bold"])
write_log(", ", color="white", attrs=["dark"])
write_log(cpu, color="red", attrs=["bold"])
def print_iteration(prefix: str, cur: str, sep: str, total: str) -> None:
"""Format and print the current iteration header."""
write_log(prefix, color="magenta", attrs=["bold", "underline"])
write_log(cur, color="green", attrs=["bold", "underline"])
write_log(sep, color="magenta", attrs=["bold", "underline"])
write_log(total, color="blue", attrs=["bold", "underline"], end="\n")
text = ""
while c := sys.stdin.read(1):
text += c
line = text
text = ""
if match := re.match(r"(Allocating file: )"
rf"({SIZE}M-(data|hole|mixed-\d+(d|h)))( ...)", line):
filetype = match.group(3) if match.group(4) is None else match.group(4)
print_allocation(match.group(1), match.group(2),
filetype, match.group(5))
elif match := re.match(r"( \[Done: )(\d+\.\d+s)(\]\n)", line):
print_allocation_done(match.group(1), match.group(2), match.group(3))
elif match := re.match(rf"(Reading: )({SIZE}M-(data|hole|mixed-\d+(d|h)))"
r"( \()((un)?(cached|known))( on [\w-]*\))\n",
line):
filetype = match.group(3) if match.group(4) is None else match.group(4)
print_reading(match.group(1), match.group(2), match.group(5),
match.group(6), match.group(9))
elif match := re.match(r"\d+ bytes \([\w,\. ]*\) copied, (\d+\.\d+ s), "
r"(\d+\.?\d+ [MG]B/s)\n", line):
print_stats_1(match.group(1), match.group(2))
elif match := re.match(r"(\d+\.\d+)(s kern), (\d+% cpu)", line):
print_stats_2(match.group(1), match.group(2), match.group(3))
elif match := re.match(r"\d+\+\d+ records (in|out)\n", line):
pass
elif match := re.match(r"(Iteration )(\d+)( / )(\d+)\n", line):
print_iteration(match.group(1), match.group(2),
match.group(3), match.group(4))
elif c == "\n":
write_log(line)
else:
text = line

View File

@ -1,86 +1,181 @@
"""Colorize xfstests.zsh output."""
import sys import sys
import re import re
import termcolor import termcolor
PROTO_COLORS = { "tcp":"white", "rdma":"yellow" }
PROTO = sys.argv[1]
VERS_COLORS = { "v3":"red", "v4.0":"green", "v4.1":"blue", "v4.2":"yellow" } PROTO_COLORS = {"tcp": "white", "rdma": "yellow"}
STATUS_COLORS = {"Ran": "cyan", "Not run": "magenta", "Failures": "red"}
VERS_COLORS = {"v3": "red", "v4.0": "green", "v4.1": "blue", "v4.2": "yellow"}
PROTO = sys.argv[1]
VERS = f"v{sys.argv[2]}" VERS = f"v{sys.argv[2]}"
COLOR = VERS_COLORS[VERS] COLOR = VERS_COLORS[VERS]
PROTO_COLOR = PROTO_COLORS[PROTO]
CONFIG = []
prefix = termcolor.colored("[", "white", attrs=["bold"]) PREFIX = termcolor.colored("[", "white", attrs=["bold"])
prefix += termcolor.colored(PROTO.rjust(4), PROTO_COLORS[PROTO], attrs=["dark"]) PREFIX += termcolor.colored(PROTO.rjust(4), PROTO_COLOR, attrs=["dark"])
prefix += termcolor.colored(",", "white", attrs=["bold"]) PREFIX += termcolor.colored(",", "white", attrs=["bold"])
prefix += termcolor.colored(VERS.ljust(4), COLOR, attrs=["bold"]) PREFIX += termcolor.colored(VERS.ljust(4), COLOR, attrs=["bold"])
prefix += termcolor.colored("] ", "white", attrs=["bold"]) PREFIX += termcolor.colored("] ", "white", attrs=["bold"])
CONFIG = [ ]
def add_config(line): def add_config(line: str) -> None:
[ key, val ] = [ s.strip() for s in re.split("--", line) ] """Format a configuration entry and add it to the CONFIG list."""
[key, val] = [s.strip() for s in re.split("--", line)]
if key == "MKFS_OPTIONS": if key == "MKFS_OPTIONS":
return return
elif key == "MOUNT_OPTIONS" and val[:2] != "-o": elif key == "MOUNT_OPTIONS" and val[:2] != "-o":
return return
parts = [ prefix ] parts = [PREFIX]
parts.append(termcolor.colored(key.ljust(14), COLOR, attrs=["bold"])) parts.append(termcolor.colored(key.ljust(14), COLOR, attrs=["bold"]))
parts.append(termcolor.colored("-- ", "white", attrs=["dark"])) parts.append(termcolor.colored("-- ", "white", attrs=["dark"]))
parts.append(termcolor.colored(val, "white", attrs=["bold"])) parts.append(termcolor.colored(val, "white", attrs=["bold"]))
CONFIG.append("".join(parts)) CONFIG.append("".join(parts))
def print_config():
def print_config() -> None:
"""Print out the collected configuration entries and clear the list."""
if len(CONFIG) > 0: if len(CONFIG) > 0:
print("\n".join(CONFIG), end="\n\n") print("\n".join(CONFIG), end="\n\n")
CONFIG.clear() CONFIG.clear()
def print_test(match):
parts = [ prefix ] def print_test(match: re.Match) -> None:
"""Format and print a single testcase."""
parts = [PREFIX]
parts.append(termcolor.colored(match.group(1), COLOR, attrs=["bold"])) parts.append(termcolor.colored(match.group(1), COLOR, attrs=["bold"]))
if m := re.match("(\[not run\])(.*?\n)", match.group(2)): if m := re.match(r"(\[not run\])(.*?\n)", match.group(2)):
return return
parts.append(termcolor.colored(m.group(1), "yellow")) parts.append(termcolor.colored(m.group(1), "yellow"))
parts.append(termcolor.colored(m.group(2), "white", attrs=["bold"])) parts.append(termcolor.colored(m.group(2), "white", attrs=["bold"]))
elif m := re.match("(\d+s)( ... +)(\d+s\n)", match.group(2)): elif m := re.match(r"(\d+s)( ... +)(\d+s\n)", match.group(2)):
parts.append(termcolor.colored(m.group(1), "green")) parts.append(termcolor.colored(m.group(1), "green"))
parts.append(termcolor.colored(m.group(2), "white", attrs=["dark"])) parts.append(termcolor.colored(m.group(2), "white", attrs=["dark"]))
parts.append(termcolor.colored(m.group(3), "green")) parts.append(termcolor.colored(m.group(3), "green"))
elif re.match("\d+s\n", match.group(2)): elif re.match(r"\d+s\n", match.group(2)):
parts.append(termcolor.colored(match.group(2), "green")) parts.append(termcolor.colored(match.group(2), "green"))
else: # Test failed else: # Test failed
line = re.sub("\]-", "\] -", match.group(2)) line = re.sub(r"\]-", r"\] -", match.group(2))
parts.append(termcolor.colored(line, "magenta", attrs=["bold"])) parts.append(termcolor.colored(line, "magenta", attrs=["bold"]))
print("".join(parts), end="") print("".join(parts), end="")
def print_diff(line):
print(prefix, end="") def print_diff(line: str) -> None:
if re.match(" +@@.*?@@\n", line): """Format and print out a single line of a failing test diff."""
print(PREFIX, end="")
if re.match(r" +@@.*?@@\n", line):
termcolor.cprint(line, color="yellow", attrs=["dark"], end="") termcolor.cprint(line, color="yellow", attrs=["dark"], end="")
elif re.match(" +-", line): elif re.match(r" +-", line):
termcolor.cprint(line, color="magenta", attrs=["dark"], end="") termcolor.cprint(line, color="magenta", attrs=["dark"], end="")
elif re.match(" +\+", line): elif re.match(r" +\+", line):
termcolor.cprint(line, color="cyan", attrs=["dark"], end="") termcolor.cprint(line, color="cyan", attrs=["dark"], end="")
elif re.match(" +\(Run", line): elif re.match(r" +\(Run", line):
termcolor.cprint(line, color="magenta", attrs=["bold"], end="") termcolor.cprint(line, color="magenta", attrs=["bold"], end="")
else: else:
termcolor.cprint(line, color="white", attrs=["dark"], end="") termcolor.cprint(line, color="white", attrs=["dark"], end="")
def print_test_list(status: str, line: str) -> None:
"""Format and print the list of tests that ran, failed, or were skipped."""
tests = dict()
_tmp = [t.split("/") for t in line[len(status)+1:].split()]
[tests.setdefault(t[0], []).append(t[1]) for t in _tmp]
for key in sorted(tests.keys()):
parts = [PREFIX]
parts.append(termcolor.colored(status, STATUS_COLORS[status],
attrs=["bold"]))
parts.append(termcolor.colored(": ", "white", attrs=["bold"]))
parts.append(termcolor.colored(key, color=COLOR, attrs=["bold"]))
parts.append(termcolor.colored(": [", "white", attrs=["bold"]))
for i, test_num in enumerate(sorted(tests[key])):
sep = termcolor.colored(", ", attrs=["bold"] if i > 0 else "")
if i != 0:
parts.append(sep)
attr = ["bold", "dark"] if i % 2 else ["bold"]
parts.append(termcolor.colored(test_num, STATUS_COLORS[status],
attrs=attr))
parts.append(termcolor.colored("]", "white", attrs=["bold"]))
print("".join(parts))
def print_failed(match: re.Match) -> None:
"""Format and print the number of failing tests."""
parts = [PREFIX]
parts.append(termcolor.colored("Failed ", "red", attrs=["bold"]))
parts.append(termcolor.colored(match.group(1), COLOR, attrs=["bold"]))
parts.append(termcolor.colored(" of ", "red", attrs=["bold"]))
parts.append(termcolor.colored(match.group(2), COLOR, attrs=["bold"]))
parts.append(termcolor.colored(" tests", "red", attrs=["bold"]))
print("".join(parts))
def print_all_passed(match: re.Match) -> None:
"""Format and print a status line if all tests pass."""
parts = [PREFIX]
parts.append(termcolor.colored("Passed all ", "green", attrs=["bold"]))
parts.append(termcolor.colored(match.group(1), COLOR, attrs=["bold"]))
parts.append(termcolor.colored(" tests", "green", attrs=["bold"]))
print("".join(parts))
def print_xunit(match: re.Match) -> None:
"""Format and print the xunit file location."""
parts = [PREFIX]
parts.append(termcolor.colored(match.group(1), PROTO_COLOR,
attrs=["dark", "bold"]))
parts.append(termcolor.colored(": ", "white", attrs=["bold"]))
parts.append(termcolor.colored(match.group(2), COLOR, attrs=["bold"]))
print("".join(parts))
def print_xfstestsdb(match: re.Match) -> None:
"""Format and print the xfstestsdb xunit-add line."""
parts = [PREFIX]
parts.append(termcolor.colored(match.group(1).title(), PROTO_COLOR,
attrs=["dark", "bold"]))
parts.append(termcolor.colored(" '", "white", attrs=["bold"]))
parts.append(termcolor.colored(match.group(2), COLOR,
attrs=["bold"]))
parts.append(termcolor.colored("' ", "white", attrs=["bold"]))
parts.append(termcolor.colored(match.group(3), PROTO_COLOR,
attrs=["dark", "bold"]))
parts.append(termcolor.colored(match.group(4), COLOR, attrs=["bold"]))
parts.append(termcolor.colored(match.group(5), PROTO_COLOR,
attrs=["dark", "bold"]))
parts.append(termcolor.colored(" #", "white", attrs=["bold"]))
parts.append(termcolor.colored(match.group(6), COLOR,
attrs=["bold"]))
print("".join(parts))
for line in sys.stdin: for line in sys.stdin:
if line == "\n": if line == "\n":
print_config() print_config()
elif re.match("^[A-Z_]+[ ]+-- .*?\n", line): elif re.match("^[A-Z_]+[ ]+-- .*?\n", line):
if match := re.match("(^PLATFORM(.*?)PREEMPT)(.*?\n)", line): if match := re.match("(^PLATFORM(.*?)PREEMPT.*?) (.*?\n)", line):
add_config(match.group(1)) add_config(match.group(1))
line = f"COMPILED -- {match.group(3)}" line = f"COMPILED -- {match.group(3)}"
add_config(line) add_config(line)
elif match := re.match("(^[a-z]+/[\d]+[ | ]+)(.*?\n)", line): elif match := re.match(r"(^[a-z]+/\d+[ | ]+)(.*?\n)", line):
print_test(match) print_test(match)
elif match := re.match("^ (.*?)\n", line): elif match := re.match("^ (.*?)\n", line):
print_diff(line) print_diff(line)
elif match := re.match(r"^(Ran|Not run|Failures):([ a-z]+/\d+)+\n", line):
print_test_list(match.group(1), line)
elif match := re.match(r"^Failed (\d+) of (\d+) tests\n", line):
print_failed(match)
elif match := re.match(r"^Passed all (\d+) tests\n", line):
print_all_passed(match)
elif match := re.match(r"(^Xunit report): (.*?.xml)\n", line):
print_xunit(match)
elif match := re.match(r"(^added) '(.*?)' (with )"
r"(\d+)( testcases to run) #(\d+)\n", line):
print_xfstestsdb(match)
else: else:
#pass print(PREFIX + line, end="")
print(prefix, end="")
print(line, end="")

101
common.zsh Normal file
View File

@ -0,0 +1,101 @@
#!/bin/zsh
##############################
# #
# NFS client configuration #
# #
##############################
CLIENT=(client)
MOUNTPOINT=(/mnt/test)
SCRATCHMNT=(/mnt/scratch)
##############################
# #
# NFS server configuration #
# #
##############################
SERVER=(server)
EXPORT=(/srv/xfs/test)
SCRATCH=(/srv/xfs/scratch)
NO_SERVER_ACCESS=()
###########################
# #
# General configuration #
# #
###########################
BIN=$HOME/.local/bin
COLORS=$BIN/colors
DMESG=()
PROTO=(tcp)
SRVDMESG=()
USER=$(whoami)
VERSION=(3 4)
######################
# #
# Shared functions #
# #
######################
function client_run()
{
zparseopts -D -K t=TERMINAL
[[ ! -z $TERMINAL ]] && SSH_OPT="-t"
ssh $SSH_OPT ${CLIENT[-1]} sudo run.zsh $*
}
function client_setup()
{
ssh ${CLIENT[-1]} sudo setup.zsh $*
}
function setup_client_func()
{
client_setup testdirs.zsh ${SERVER[-1]} ${EXPORT[-1]} \
${MOUNTPOINT[-1]} $USER
}
function prepare_to_test()
{
$BIN/vm.zsh boot ${CLIENT[-1]} ${SERVER[-1]}
$BIN/install-scripts.zsh ${CLIENT[-1]}
if [ ${#DMESG} -gt 0 ]; then
ssh ${CLIENT[-1]} "sudo dmesg --clear"
fi
if [ ${#SRVDMESG} -gt 0 ]; then
ssh ${SERVER[-1]} "sudo dmesg --clear"
fi
if [ ${#RDMA} -gt 0 ]; then
PROTO+=(rdma)
if [ ${#NO_SERVER_ACCESS} -gt 0 ]; then
$BIN/rdma.zsh ${RDMA[-1]} ${CLIENT[-1]}
else
$BIN/rping.zsh ${RDMA[-1]} ${CLIENT[-1]} ${SERVER[-1]}
fi
fi
setup_client_func
check_versions
echo
}
function check_versions()
{
valid=(3 4.0 4.1 4.2)
if [[ ${VERSION[(ie)4]} -le ${#VERSION} ]]; then
VERSION+=(4.0 4.1 4.2)
fi
VERSION=(${(ou)VERSION})
VERSION=(${VERSION:*valid})
}
TRAPEXIT()
{
if [ ${#DMESG} -gt 0 ]; then
ssh ${CLIENT[-1]} "sudo dmesg --color=always"
fi
if [ ${#SRVDMESG} -gt 0 ]; then
ssh ${SERVER[-1]} "sudo dmesg --color=always"
fi
}

View File

@ -2,15 +2,24 @@
function _cthon.zsh() { function _cthon.zsh() {
_arguments \ _arguments \
{-a,--all}'[run all tests]' \
{-b,--basic}'[run basic tests]' \
{-c,--client}'[the client to test]: : _alternative {-c,--client}'[the client to test]: : _alternative
"hosts\:hosts\: _ssh_hosts" "hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \ "domains\:domains\: _libvirt"' \
--nconnect'[number of connections]: :($(seq 1 32))' \ --dmesg'[print client dmesg log after running tests]' \
{-g,--general}'[run general tests]' \
{-l,--locking}'[run locking tests]' \
--no-server-access'[do not attempt to ssh into the server]' \
\*{-o,--options}'[mount options for all mounts]: :' \
--krb5'[run tests with sec=krb5]' \ --krb5'[run tests with sec=krb5]' \
--srvdmesg'[print server dmesg log after running tests]' \
{-p,--mountpoint}'[the directory to mount the server]: : _files -/' \ {-p,--mountpoint}'[the directory to mount the server]: : _files -/' \
{-r,--rdma}'[test using rdma]: :(rxe siw)' \ {-r,--rdma}'[test using rdma]: :(rxe siw)' \
{-s,--server}'[the server to test against]: : _alternative {-s,--server}'[the server to test against]: : _alternative
"hosts\:hosts\: _ssh_hosts" "hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \ "domains\:domains\: _libvirt"' \
{-S,--special}'[run special tests]' \
\*{-v,--version}+'[the nfs version to test (default=all)]: :(3 4 4.0 4.1 4.2)' \
{-x,--export}'[the exported directory on the server]: : _files -/' {-x,--export}'[the exported directory on the server]: : _files -/'
} }

View File

@ -1,7 +1,11 @@
#compdef makelinux.zsh #compdef makelinux.zsh
function _makelinux.zsh() { function _makelinux.zsh() {
_arguments '*: :_make' _arguments \
--clang'[compile using clang]' \
--gcc'[compile using gcc]' \
--arm64'[cross-compile for arm64]' \
'*: :_make'
} }
_makelinux.zsh "$@" _makelinux.zsh "$@"

View File

@ -0,0 +1,15 @@
#compdef nfstest_rplus.zsh
function _nfstest_rplus.zsh() {
_arguments \
{-c,--client}'[the client to test]: : _alternative
"hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \
--dmesg'[print client dmesg log after running tests]' \
--srvdmesg'[print server dmesg log after running tests]' \
{-p,--mountpoint}'[the directory to mount the server]: : _files -/' \
{-s,--server}'[the server to test against]: : _alternative
"hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \
{-x,--export}'[the exported directory on the server]: : _files -/'
}

View File

@ -0,0 +1,20 @@
#compdef read_plus.zsh
function _read_plus.zsh() {
_arguments \
{-c,--client}'[the client to test]: : _alternative
"hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \
{-d,--direct}'[call dd with iflag=direct]' \
--dmesg'[print client dmesg log after running tests]' \
{-f,--file}'[write output to file]: : _files' \
{-i,--iterations}'[number of times to repeat the test]: :($(seq 100))' \
{-p,--mountpoint}'[the directory to mount the server]: : _files -/' \
--no-server-vmtouch'[do not vmtouch the files on the server]' \
--srvdmesg'[print server dmesg log after running tests]' \
{-s,--server}'[the server to test against]: : _alternative
"hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \
{-x,--export}'[the exported directory on the server]: : _files -/' \
{-z,--size}'[the size of the test files]: :($(seq 5120))'
}

View File

@ -0,0 +1,10 @@
#compdef submit-patches.zsh
function _submit-patches.zsh() {
_arguments \
--linus'[submit to Linus Torvalds]' \
--nfs'[submit to nfs maintainers]' \
--nfsd'[submit to nfsd maintainers]' \
--nfsutils'[submit to nfs-utils maintainers]' \
{--xfstests,--fstests}'[submit to xfstests maintainers]'
}

View File

@ -5,14 +5,30 @@ function _xfstests.zsh() {
{-c,--client}'[the client to test]: : _alternative {-c,--client}'[the client to test]: : _alternative
"hosts\:hosts\: _ssh_hosts" "hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \ "domains\:domains\:($(virsh list --all --name))"' \
{-g,--group}'[the xfstests group to run]: :($(_list_xfstests_groups))' \
{-k,--scratch}'[the exported scratch directory on the server]: : _files -/' \ {-k,--scratch}'[the exported scratch directory on the server]: : _files -/' \
{-p,--mountpoint}'[the directory to mount the server]: : _files -/' \ {-p,--mountpoint}'[the directory to mount the server]: : _files -/' \
--nconnect'[number of connections]: :($(seq 1 32))' \ --no-scratch'[do not use a scratch mount during testing]' \
--no-server-access'[do not attempt to ssh into the server]' \
\*{-o,--options}'[mount options for all mounts]: :' \
{-r,--rdma}'[test using rdma]: :(rxe siw)' \ {-r,--rdma}'[test using rdma]: :(rxe siw)' \
{-q,--scratchmnt}'[the directory to mount the scratch export]: : _files -/' \ {-q,--scratchmnt}'[the directory to mount the scratch export]: : _files -/' \
{-s,--server}'[the server to test against]: : _alternative {-s,--server}'[the server to test against]: : _alternative
"hosts\:hosts\: _ssh_hosts" "hosts\:hosts\: _ssh_hosts"
"domains\:domains\:($(virsh list --all --name))"' \ "domains\:domains\:($(virsh list --all --name))"' \
\*{-v,--version}+'[the nfs version to test (default=all)]: :(3 4.0 4.1 4.2)' \ \*{-v,--version}+'[the nfs version to test (default=all)]: :(3 4 4.0 4.1 4.2)' \
{-x,--export}'[the exported directory on the server]: : _files -/' {-x,--export}'[the exported directory on the server]: : _files -/'
} }
function _list_xfstests_groups() {
if [ ! -f /tmp/xfstests.groups.completion ]; then
find $HOME/Programs/xfstests-dev -name group.list \
-exec grep -P '^\d+' '{}' \; | \
awk '{$1=""; print $0}' | \
awk -F\# '{print $1}' | \
grep -o -E '\w+' | \
sort | uniq > /tmp/xfstests.groups.completion
fi
cat /tmp/xfstests.groups.completion
}

View File

@ -1,43 +1,60 @@
#!/bin/zsh -e #!/bin/zsh -e
CLIENT=(client) source common.zsh
SERVER=(server) TESTS=(-a)
EXPORT=(/srv/test)
MOUNTPOINT=(/mnt/test)
zparseopts -F -K \ zparseopts -F -K \
a+=TESTS -all+=TESTS \
b+=TESTS -basic+=TESTS \
c:=CLIENT -client:=CLIENT \ c:=CLIENT -client:=CLIENT \
-dmesg=DMESG -srvdmesg=SRVDMESG \
g+=TESTS -general+=TESTS \
l+=TESTS -locking+=TESTS \
o+:=MNTOPTS -options+:=MNTOPTS \
p:=MOUNTPOINT -mountpoint:=MOUNTPOINT \ p:=MOUNTPOINT -mountpoint:=MOUNTPOINT \
-nconnect:=NCONNECT \ -no-server-access=NO_SERVER_ACCESS \
-krb5=KRB5 \ -krb5=KRB5 \
r:=RDMA -rdma:=RDMA \ r:=RDMA -rdma:=RDMA \
S+=TESTS -special+=TESTS \
s:=SERVER -server:=SERVER \ s:=SERVER -server:=SERVER \
x:=EXPORT -export:=EXPORT x:=EXPORT -export:=EXPORT \
v+:=VERSION -version+:=VERSION
BIN=$HOME/bin SEC=(sys)
COLOR=$BIN/colors/cthon.py ARGS=($(echo $MNTOPTS | sed 's/-o /--mntopt /g'))
RUN_CTHON="cd cthon04 && sudo ./runcthon"
USER=$(whoami)
# prepare_to_test
# Prepare to test
# if [[ ${TESTS[(ie)-a]} -le ${#TESTS} ]]; then
$BIN/vm.zsh boot ${CLIENT[-1]} ${SERVER[-1]} TESTS=(-b -g -s -l)
$BIN/install-scripts.zsh ${CLIENT[-1]}
if [ ${#RDMA} -gt 0 ]; then
RUN_CTHON="$RUN_CTHON --rdma"
$BIN/rping.zsh ${RDMA[-1]} ${CLIENT[-1]} ${SERVER[-1]}
fi
if [ ${#NCONNECT} -gt 0 ]; then
RUN_CTHON="$RUN_CTHON --nconnect ${NCONNECT[-1]}"
fi fi
if [ ${#KRB5} -gt 0 ]; then if [ ${#KRB5} -gt 0 ]; then
RUN_CTHON="$RUN_CTHON --dokrb5" SEC+=(krb5 krb5i krb5p)
fi fi
ssh ${CLIENT[-1]} "sudo setup-testdirs.zsh ${SERVER[-1]} ${EXPORT[-1]} ${MOUNTPOINT[-1]} $USER" | python $COLOR for vers in $VERSION; do
echo ARGS+=("--version $vers")
done
#
# Run tests function run_cthon_zsh()
# {
ssh ${CLIENT[-1]} "$RUN_CTHON --server ${SERVER[-1]} --serverdir ${EXPORT[-1]}/$USER 2>&1" | python -u $COLOR client_run cthon.zsh --server ${SERVER[-1]} --export ${EXPORT[-1]} \
--mountpoint ${MOUNTPOINT[-1]} --user $USER \
--proto $2 --mntopt sec=$3 $1 $ARGS \
| python -u $COLORS/cthon.py
}
ret=0
set +e
date | python -u $COLORS/cthon.py
for test in $TESTS; do
for proto in $PROTO; do
for sec in $SEC; do
run_cthon_zsh $test $proto $sec
ret=$((ret+$?))
done
done
done
exit $ret

View File

@ -1,14 +1,31 @@
#!/bin/zsh -e #!/bin/zsh -e
source common.zsh
autoload colors autoload colors
colors colors
OPTS=(--clang)
zparseopts -D -K -clang+=OPTS -gcc+=OPTS -arm64+=OPTS -i686+=OPTS
if [ "$#" -lt 1 ]; then if [ "$#" -lt 1 ]; then
echo "Usage: $0 {remote host, ...}" echo "Usage: $0 {remote host, ...}"
exit 1 exit 1
fi fi
makepkg -f case ${OPTS[-1]} in
deploypkg.zsh $(makepkg --packagelist) $* --clang) export CC=clang ;;
--gcc) export CC=gcc ;;
--arm64) export CC=gcc
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
;;
--i686) export CC=gcc
export ARCH=i386
;;
esac
PKGDEST=packages makepkg -f
PKGDEST=packages deploypkg.zsh $(makepkg --packagelist) $*
pkgname=$(grep ^pkgname PKGBUILD | awk -F= '{print $2}') pkgname=$(grep ^pkgname PKGBUILD | awk -F= '{print $2}')
@ -22,7 +39,7 @@ echo
vm.zsh reboot $* vm.zsh reboot $*
echo echo
tags=($(python /home/anna/bin/colors/vm.py $*)) tags=($(FORCE_COLOR=1 python $COLORS/vm.py $*))
for ((i=1; i<=$#; i++)); do for ((i=1; i<=$#; i++)); do
echo "${tags[i]} $fg_bold[default]$(ssh ${@[i]} uname -rsn)$reset_color" echo "${tags[i]} $fg_bold[default]$(ssh ${@[i]} uname -rsn)$reset_color"
done done

View File

@ -1,5 +1,5 @@
#!/bin/zsh #!/bin/zsh
colors="$HOME/bin/colors" source common.zsh
if [ "$#" -lt 2 ]; then if [ "$#" -lt 2 ]; then
echo "Usage: $0 /path/to/package {remote host, ...}" echo "Usage: $0 /path/to/package {remote host, ...}"
@ -12,11 +12,12 @@ shift
function deploy_package() { function deploy_package() {
ssh $1 "mkdir -pv pkg" 2>&1 | sed -e "s/^/$2 /" ssh $1 "mkdir -pv pkg" 2>&1 | sed -e "s/^/$2 /"
script -q -c "scp $pkg $1:pkg/ 2>&1" 2>&1 | sed -e "s/^/$2 /" script -q -c "scp $pkg $1:pkg/ 2>&1" 2>&1 | sed -e "s/^/$2 /"
ssh $1 "sudo pacman --noconfirm -U pkg/$pkg" | python $colors/pacman.py $2 ssh $1 "sudo pacman --noconfirm -U pkg/$pkg" | python $COLORS/pacman.py $2
} }
$HOME/bin/vm.zsh boot $* $BIN/vm.zsh boot $*
tags=($(python $colors/vm.py $*))
tags=($(FORCE_COLOR=1 python $COLORS/vm.py $*))
for ((i=1; i<=$#; i++)); do for ((i=1; i<=$#; i++)); do
deploy_package ${@[i]} ${tags[i]} & deploy_package ${@[i]} ${tags[i]} &
done done

View File

@ -1,19 +1,19 @@
#!/bin/zsh #!/bin/zsh
source common.zsh
BIN=$HOME/bin SCRIPTS=(grub-list.zsh setup.zsh setup/ run/)
SCRIPTS=(grub-list.zsh setup-testdirs.zsh \
setup-xfstests.zsh run-xfstests.zsh)
function install_script() { function install_script() {
ssh $1 mkdir -p bin/ ssh $1 mkdir -p .local/bin/{setup,run}
echo -n "$2 Copying files ..." echo -n "$2 Copying files ..."
for script in $SCRIPTS; do for script in $SCRIPTS; do
scp -q $BIN/$script $1:bin/ scp -qr $BIN/$script $1:.local/bin/
done done
ssh $1 cp .local/bin/setup.zsh .local/bin/run.zsh
echo " done" echo " done"
} }
tags=($(python $BIN/colors/vm.py $*)) tags=($(FORCE_COLOR=1 python $COLORS/vm.py $*))
for ((i=1; i<=${#@}; i++)); do for ((i=1; i<=${#@}; i++)); do
install_script ${@[i]} ${tags[i]} install_script ${@[i]} ${tags[i]}
done done

View File

@ -1,117 +1,151 @@
#!/usr/bin/python #!/usr/bin/python
"""Iterate through KConfig options, enabling them one by one."""
import argparse import argparse
import pathlib import pathlib
import re import re
import subprocess import subprocess
import sys import sys
import termcolor import termcolor
import typing
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("-q", "--quick", action="store_true", dest="quick", parser.add_argument("-q", "--quick", action="store_true", dest="quick",
help="Only compile the subdirectory containing the Kconfig file") help="Only compile the subdirectory "
parser.add_argument("kconfig", metavar="Kconfig", nargs=1, help="Path to Kconfig file") "containing the Kconfig file")
parser.add_argument("makeargs", metavar="Make Arguments", nargs="*", help="Options to pass to make") parser.add_argument("kconfig", metavar="Kconfig", nargs=1,
help="Path to Kconfig file")
parser.add_argument("makeargs", metavar="Make Arguments", nargs="*",
help="Options to pass to make")
Args = parser.parse_args() Args = parser.parse_args()
Kconfig = pathlib.Path(Args.kconfig[0]) Kconfig = pathlib.Path(Args.kconfig[0])
Config = pathlib.Path("scripts/config").absolute() Config = pathlib.Path("scripts/config").absolute()
Make = pathlib.Path("~/bin/makelinux.zsh").expanduser() Make = pathlib.Path("~/.local/bin/makelinux.zsh").expanduser()
MakeArg = Args.makeargs + ([ f"{str(Kconfig)}/" ] if Args.quick else [ ]) MakeArg = Args.makeargs + ([f"{str(Kconfig)}/"] if Args.quick else [])
Options = dict() Options = dict()
Colors = { "n" : "grey", "y" : "green", "m" : "cyan" } Colors = {"n": "dark_grey", "y": "green", "m": "cyan"}
Attrs = { "y" : [ "bold" ], "m" : [ "bold" ] } Attrs = {"y": ["bold"], "m": ["bold"]}
NameLen = 0 NameLen = 0
if Kconfig.is_dir(): if Kconfig.is_dir():
Kconfig = Kconfig / "Kconfig" Kconfig = Kconfig / "Kconfig"
def assert_exists(path):
for path in [Kconfig, Make, Config]:
if not path.exists(): if not path.exists():
print(f"Error: {path} does not exist!") print(f"Error: {path} does not exist!")
sys.exit(1) sys.exit(1)
assert_exists(Kconfig)
assert_exists(Make)
assert_exists(Config)
class Option: class Option:
def __init__(self, opt): """Represents a single CONFIG_* KConfig Option."""
def __init__(self, opt: str):
"""Initialize our Option class."""
lines = opt.splitlines() lines = opt.splitlines()
self.name = lines[0].strip() self.name = lines[0].strip()
self.type = lines[1].strip().split()[0] self.type = lines[1].strip().split()[0]
self.state = "y" self.state = "y"
self.res = None self.res = None
if search := re.search("\sdepends on (.*?)\n", opt): if search := re.search(r"\sdepends on (.*?)\n", opt):
depends = search.group(1).strip() depends = search.group(1).strip()
depends = [ d.strip() for d in re.split("[&&|=m|=y|=n]", depends) ] depends = [d.strip() for d in re.split("[&&|=m|=y|=n]", depends)]
self.depends = set([ d for d in depends if len(d) > 0 ]) self.depends = set([d for d in depends if len(d) > 0])
else: else:
self.depends = set() self.depends = set()
def __repr__(self): def __repr__(self) -> str:
"""Return a string representation of this Option."""
return f"{self.name}:{self.type}" return f"{self.name}:{self.type}"
def __lt__(self, rhs): def __lt__(self, rhs: typing.Self) -> bool:
if self.name.endswith("DEBUG"): return False """Check if this option is less than the `rhs` option."""
if rhs.name.endswith("DEBUG"): return True if self.name.endswith("DEBUG"):
return False
if rhs.name.endswith("DEBUG"):
return True
return self.name in rhs.dependencies() return self.name in rhs.dependencies()
def dependencies(self): def dependencies(self) -> set[typing.Self]:
"""Get a set of dependencies for this Option."""
ret = self.depends.copy() ret = self.depends.copy()
for dep in self.depends: for dep in self.depends:
if (opt := Options.get(dep)) is not None: if (opt := Options.get(dep)) is not None:
ret.update(opt.dependencies()) ret.update(opt.dependencies())
return ret return ret
def disable(self): def disable(self) -> None:
subprocess.run([ Config ] + [ "--disable", self.name ]).check_returncode() """Disable this Option."""
subprocess.run([Config] + ["--disable", self.name]).check_returncode()
self.state = "n" self.state = "n"
def enable(self): def enable(self) -> None:
"""Enable this Option."""
how = "--module" if self.type == "tristate" else "--enable" how = "--module" if self.type == "tristate" else "--enable"
subprocess.run([ Config ] + [ how, self.name ]).check_returncode() subprocess.run([Config] + [how, self.name]).check_returncode()
self.state = "m" if self.type == "tristate" else "y" self.state = "m" if self.type == "tristate" else "y"
def print(self): def print(self) -> None:
"""Print out this option (in color!)."""
print(" ", end="") print(" ", end="")
termcolor.cprint(self.name, Colors.get(self.state), attrs=["bold", "dark"], end="") termcolor.cprint(self.name, Colors.get(self.state),
attrs=["bold", "dark"], end="")
termcolor.cprint("=", "white", attrs=["bold"], end="") termcolor.cprint("=", "white", attrs=["bold"], end="")
termcolor.cprint(self.state, Colors.get(self.state), attrs=["bold", "dark"]) termcolor.cprint(self.state, Colors.get(self.state),
attrs=["bold", "dark"])
def print_result(self) -> None:
"""Print out this option and result."""
attrs = [] if self.res is None else ["bold"]
def print_result(self):
match self.res: match self.res:
case True: result = ("Success", "green") case True: result = ("Success", "green")
case False: result = ("Failed", "red") case False: result = ("Failed", "red")
case _: result = ("Not Run", "yellow") case _: result = ("Not Run", "yellow")
termcolor.cprint(" " + self.name + " ", Colors.get(self.state), attrs=["bold", "dark"], end="")
termcolor.cprint(" " * (NameLen - len(self.name)), "grey", attrs=["underline"], end="") termcolor.cprint(" " + self.name + " ", Colors.get(self.state),
termcolor.cprint(" " + result[0], result[1], attrs=["bold", "dark"]) attrs=attrs, end="")
termcolor.cprint(" " * (NameLen - len(self.name)), "grey",
attrs=["underline"], end="")
termcolor.cprint(" " + result[0], result[1], attrs=attrs)
with open(Kconfig) as f: with open(Kconfig) as f:
regex = re.compile("\nconfig") regex = re.compile("\nconfig")
opts = [ Option(opt) for opt in regex.split(f.read()) if opt[0] != "#" ] opts = [Option(opt) for opt in regex.split(f.read()) if opt[0] != "#"]
Options = { opt.name:opt for opt in opts if opt.type in [ "bool", "tristate" ]} Options = {opt.name: opt for opt in opts
if opt.type in ["bool", "tristate"]}
options = list(Options.values()) options = list(sorted(Options.values()))
options.sort()
def make_opt(option):
def make_opt(option: Option) -> None:
"""Enable and build a single option."""
option.enable() option.enable()
print() print()
for o in options: o.print() for o in options:
o.print()
option.res = False option.res = False
subprocess.run([ Make ] + [ "olddefconfig" ]).check_returncode() subprocess.run([Make] + ["olddefconfig"]).check_returncode()
subprocess.run([ Make ] + MakeArg).check_returncode() subprocess.run([Make] + MakeArg).check_returncode()
option.res = True option.res = True
try: try:
for opt in options: NameLen = max(NameLen, len(opt.name) + 2) for opt in options:
for opt in options: opt.disable() NameLen = max(NameLen, len(opt.name) + 2)
for opt in options: make_opt(opt) opt.disable()
for opt in options:
make_opt(opt)
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
finally: finally:
termcolor.cprint(f"\nKconfig Results:", "yellow", attrs=["bold", "underline"]) print()
for opt in options: opt.print_result() termcolor.cprint("Kconfig Results:", "yellow", attrs=["bold", "underline"])
if False in [ opt.res for opt in options ]: sys.exit(1) for opt in options:
opt.print_result()
if False in [opt.res for opt in options]:
sys.exit(1)

View File

@ -1,11 +1,33 @@
#!/bin/zsh #!/bin/zsh
source common.zsh
set -eo pipefail set -eo pipefail
let jobs=$(nproc)-2 let jobs=$(nproc)-2
OPTS=(--clang)
zparseopts -D -K -clang+=OPTS -gcc+=OPTS -arm64+=OPTS -i686+=OPTS -env+=OPTS
[[ -z "$ARCH" ]] && ARCH=$(uname -m)
case ${OPTS[-1]} in
--clang) CC=clang ;;
--gcc) CC=gcc ;;
--arm64) ARCH=arm64
CC=gcc
CROSS_COMPILE=aarch64-linux-gnu-
;;
--i686) ARCH=i386
CC=gcc
;;
esac
if [ -f .git/config ] && [ -f .git/HEAD ]; then if [ -f .git/config ] && [ -f .git/HEAD ]; then
REV=$(git rev-parse --short HEAD)$(git diff --quiet || echo "-dirty") REV=$(git rev-parse --short HEAD)$(git diff --quiet || echo "-dirty")
scripts/config --set-str CONFIG_LOCALVERSION "-g$REV" scripts/config --set-str CONFIG_LOCALVERSION "-g$REV"
fi fi
make -j$jobs $* | python /home/anna/bin/colors/make.py make -j$jobs CC=$CC ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE $* | python -u $COLORS/make.py
if [[ "$CC" == "clang" ]]; then
scripts/clang-tools/gen_compile_commands.py &
fi

15
nfstest_rplus.zsh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/zsh -e
source common.zsh
zparseopts -F -K \
c:=CLIENT -client:=CLIENT \
-dmesg=DMESG -srvdmesg=SRVDMESG \
p:=MOUNTPOINT -mountpoint:=MOUNTPOINT \
s:=SERVER -server:=SERVER \
x:=EXPORT -export:=EXPORT
prepare_to_test
client_run -t nfstest-rplus.zsh --server ${SERVER[-1]} \
--export ${EXPORT[-1]} \
--mountpoint ${MOUNTPOINT[-1]} \
--user $USER

View File

@ -2,10 +2,12 @@
url=git://git.linux-nfs.org/projects/anna/linux-nfs.git url=git://git.linux-nfs.org/projects/anna/linux-nfs.git
[ -z "$1" ] && tag="v5.*-rc*" || tag="$1" [ -z "$1" ] && tag="v6.*-rc*" || tag="$1"
old=$(git describe --tags --abbrev=0 --match $tag) old=$(git describe --tags --abbrev=0 --match $tag)
new=$(git describe) new=$(git describe)
echo "Subject: [GIT PULL] <INSERT SUBJECT HERE>"
echo
echo "Hi Linus," echo "Hi Linus,"
echo echo
git request-pull $old $url HEAD:$new git request-pull $old $url $new

View File

@ -1,4 +1,5 @@
#!/bin/zsh #!/bin/zsh
source common.zsh
if [ "$#" -lt 2 ]; then if [ "$#" -lt 2 ]; then
echo "Usage: $0 {rxe,siw,info,start,status,stop,off} {remote host,...}" echo "Usage: $0 {rxe,siw,info,start,status,stop,off} {remote host,...}"
@ -55,7 +56,7 @@ rdma_stop() {
} }
IFS=$'\n' IFS=$'\n'
tags=($(python /home/anna/bin/colors/vm.py ${@:2})) tags=($(FORCE_COLOR=1 python $COLORS/vm.py ${@:2}))
for vm in "${@:2}"; do for vm in "${@:2}"; do
index=${@[(ie)$vm]} index=${@[(ie)$vm]}
tag=${tags[index-1]} tag=${tags[index-1]}

86
read_plus.zsh Executable file
View File

@ -0,0 +1,86 @@
#!/bin/zsh -e
source common.zsh
SIZE=(2048)
ITERATIONS=(1)
zparseopts -D -F -K \
c:=CLIENT -client:=CLIENT \
d=DIRECT -direct=DIRECT \
-dmesg=DMESG -srvdmesg=SRVDMESG \
-no-server-vmtouch=NO_VMTOUCH \
f:=FILE -file:=FILE \
i:=ITERATIONS -iterations:=ITERATIONS \
p:=MOUNTPOINT -mountpoint:=MOUNTPOINT \
s:=SERVER -server:=SERVER \
x:=EXPORT -export:=EXPORT \
z:=SIZE -size:=SIZE
COLOR="python -u $COLORS/read_plus.py ${SIZE[-1]} ${FILE[-1]}"
IFLAG=
SRV_DIR=${EXPORT[-1]}/$USER/read_plus
TEST_DIR=${MOUNTPOINT[-1]}/read_plus
TEST_DEV=${SERVER[-1]}:$SRV_DIR
TEST_FILES=(${SIZE[-1]}M-{data,hole,mixed-{1,2,3,4,5,6,7,8,16}{d,h}})
CACHE_STATUS=(uncached cached)
TIME_CMD="sudo /usr/bin/time -f \"%Ss kern, %P cpu\""
if [ "$#" -gt 0 ]; then
TEST_FILES=($*)
fi
#
# Prepare to test
#
function setup_client_func()
{
client_setup read_plus.zsh ${SERVER[-1]} ${EXPORT[-1]} \
${MOUNTPOINT[-1]} $USER ${SIZE[-1]} \
1,2,3,4,5,6,7,8,16 | eval ${COLOR}
}
if [ ${#FILE} -gt 1 ]; then
mkdir -p $(dirname ${FILE[-1]})
[[ -f ${FILE[-1]} ]] && rm -fv ${FILE[-1]}
touch ${FILE[-1]}
fi
if [ ${#DIRECT} -gt 0 ]; then
IFLAG="iflag=direct"
fi
if [ ${#NO_VMTOUCH} -gt 0 ]; then
CACHE_STATUS=unknown
fi
prepare_to_test
function dd_file() {
echo "Reading: $1 ($2 on ${SERVER[-1]})"
case $2 in
"uncached") args="eq" ;;
"cached") args="tq" ;;
"unknown") args= ;;
esac
if [ ! -z $args ]; then
ssh ${SERVER[-1]} "sudo vmtouch -$args $SRV_DIR/$1"
fi
ssh ${CLIENT[-1]} "sudo vmtouch -eq $TEST_DIR/$1"
ssh ${CLIENT[-1]} "$TIME_CMD dd if=$TEST_DIR/$1 $IFLAG of=/dev/null bs=$3"
}
for i in $(seq ${ITERATIONS[-1]}); do
[[ $i -gt 1 ]] && echo
[[ ${#FILE} -gt 1 ]] && echo >> ${FILE[-1]}
ssh ${CLIENT[-1]} "sudo mount -o sec=sys,v4.2 $TEST_DEV $TEST_DIR"
bsize=$(ssh ${CLIENT[-1]} "mount | grep $TEST_DEV" | awk -F rsize= '{print $2}' | awk -F, '{print $1}')
if [[ ${ITERATIONS[-1]} -gt 1 ]]; then
echo "Iteration $i / ${ITERATIONS[-1]}" | eval ${COLOR}
fi
for f in $TEST_FILES; do
for cache in $CACHE_STATUS; do
dd_file $f $cache $bsize 2>&1 | eval ${COLOR}
done
done
ssh ${CLIENT[-1]} "sudo umount $TEST_DIR"
done

View File

@ -38,7 +38,7 @@ class Results(Property):
class Model(GObject.GObject, Gio.ListModel): class Model(GObject.GObject, Gio.ListModel):
def __init__(self, properties): def __init__(self, properties):
GObject.GObject.__init__(self) GObject.GObject.__init__(self)
self.properties = [ Property(p, properties[p]) for p in PROPERTIES ] self.properties = [ Property(p, properties.get(p)) for p in PROPERTIES ]
self.properties.append(Results(properties)) self.properties.append(Results(properties))
def do_get_item_type(self): return GObject.TYPE_PYOBJECT def do_get_item_type(self): return GObject.TYPE_PYOBJECT
@ -73,7 +73,9 @@ class Factory(Gtk.SignalListItemFactory):
label = listitem.get_child() label = listitem.get_child()
match self.column: match self.column:
case "Property": label.set_text(listitem.get_item().key) case "Property": label.set_text(listitem.get_item().key)
case "Value": label.set_text(listitem.get_item().value) case "Value":
value = listitem.get_item().value
label.set_text(value if value else "")
case _: label.set_text("=") case _: label.set_text("=")
def on_unbind(self, factory, listitem): def on_unbind(self, factory, listitem):

View File

@ -3,6 +3,7 @@ from gi.repository import GObject
from gi.repository import Gtk from gi.repository import Gtk
import html import html
import pathlib import pathlib
import re
import tarfile import tarfile
import xml.etree.ElementTree import xml.etree.ElementTree
@ -23,20 +24,24 @@ class SkippedTest:
self.message = elm[0].attrib["message"] self.message = elm[0].attrib["message"]
self.message = self.message.replace(test_dev, "$TEST_DEV") self.message = self.message.replace(test_dev, "$TEST_DEV")
self.message = self.message.replace(test_dir, "$TEST_DIR") self.message = self.message.replace(test_dir, "$TEST_DIR")
self.message = self.message.replace(scratch_dev, "$SCRATCH_DEV") if scratch_dev:
self.message = self.message.replace(scratch_mnt, "$SCRATCH_MNT") self.message = self.message.replace(scratch_dev, "$SCRATCH_DEV")
if scratch_mnt:
self.message = self.message.replace(scratch_mnt, "$SCRATCH_MNT")
class FailedTest: class FailedTest:
def __init__(self, elm): def __init__(self, ns, elm):
self.time = elm.attrib["time"] self.time = elm.attrib["time"]
self.system_out = Gtk.TextBuffer() self.system_out = Gtk.TextBuffer()
self.system_err = Gtk.TextBuffer() self.system_err = Gtk.TextBuffer()
for e in elm: for e in elm:
match e.tag: if e.tag == f"{ns}failure":
case "failure": self.message = e.attrib["message"] self.message = e.attrib["message"]
case "system-out": self.system_out.set_text(html.unescape(e.text)) elif e.tag == f"{ns}system-out":
case "system-err": self.system_err.set_text(html.unescape(e.text)) self.system_out.set_text(html.unescape(e.text))
elif e.tag == f"{ns}system-err":
self.system_err.set_text(html.unescape(e.text))
class TestCase(GObject.GObject): class TestCase(GObject.GObject):
@ -66,26 +71,29 @@ class TestResults:
self.versions.append(pathlib.Path(name).stem) self.versions.append(pathlib.Path(name).stem)
passed = 0 passed = 0
match = re.match(r"{.*?}", root.tag)
ns = match.group(0) if match else ""
for prop in root.attrib.keys(): for prop in root.attrib.keys():
self.set_property(prop, root.attrib[prop]) self.set_property(prop, root.attrib[prop])
for elm in root: for elm in root:
if elm.tag == "properties": if elm.tag == f"{ns}properties":
for prop in elm: for prop in elm:
self.set_property(prop.attrib["name"], prop.attrib["value"]) self.set_property(prop.attrib["name"], prop.attrib["value"])
elif elm.tag == "testcase": elif elm.tag == f"{ns}testcase":
if len(elm) == 0: if len(elm) == 0:
result = PassingTest(elm) result = PassingTest(elm)
passed += 1 passed += 1
elif elm[0].tag == "skipped": elif elm[0].tag == f"{ns}skipped":
result = SkippedTest(elm, result = SkippedTest(elm,
self.properties[self.versions[-1]]["TEST_DEV"], self.properties[self.versions[-1]]["TEST_DEV"],
self.properties[self.versions[-1]]["TEST_DIR"], self.properties[self.versions[-1]]["TEST_DIR"],
self.properties[self.versions[-1]]["SCRATCH_DEV"], self.properties[self.versions[-1]].get("SCRATCH_DEV"),
self.properties[self.versions[-1]]["SCRATCH_MNT"]) self.properties[self.versions[-1]].get("SCRATCH_MNT"))
self.skipped.add(result.message) self.skipped.add(result.message)
elif elm[0].tag == "failure": elif elm[0].tag == f"{ns}failure":
result = FailedTest(elm) result = FailedTest(ns, elm)
self.add_testcase(elm.attrib["name"], result) self.add_testcase(elm.attrib["name"], result)
self.set_property("passed", str(passed)) self.set_property("passed", str(passed))

View File

@ -124,6 +124,7 @@ class Filter(Gtk.Filter):
match type(testcase[key]): match type(testcase[key]):
case testresults.PassingTest: case testresults.PassingTest:
res = [ "passing", "passed" ] res = [ "passing", "passed" ]
search.append(f"time={testcase[key].time}")
case testresults.SkippedTest: case testresults.SkippedTest:
res = [ "skipped" ] res = [ "skipped" ]
search.append(f"message={testcase[key].message}") search.append(f"message={testcase[key].message}")
@ -171,7 +172,7 @@ class Viewer(Gtk.ScrolledWindow):
self.columnview = Gtk.ColumnView.new(model=self.selection) self.columnview = Gtk.ColumnView.new(model=self.selection)
self.columnview.add_css_class("data-table") self.columnview.add_css_class("data-table")
self.provider.load_from_data(CSS.encode()) self.provider.load_from_data(CSS, -1)
self.get_style_context().add_provider_for_display(self.get_display(), self.provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) self.get_style_context().add_provider_for_display(self.get_display(), self.provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
self.set_child(self.columnview) self.set_child(self.columnview)

View File

@ -1,4 +1,5 @@
#!/bin/zsh -e #!/bin/zsh -e
source common.zsh
if [ "$#" -ne 3 ]; then if [ "$#" -ne 3 ]; then
echo "Usage: $0 {rxe,siw} {client} {server}" echo "Usage: $0 {rxe,siw} {client} {server}"
@ -10,8 +11,7 @@ CLIENT=$2
SERVER=$3 SERVER=$3
IFS=$'\n' IFS=$'\n'
BIN=$HOME/bin tags=($(FORCE_COLOR=1 python $COLORS/vm.py $CLIENT $SERVER))
tags=($(python $BIN/colors/vm.py $CLIENT $SERVER))
$BIN/rdma.zsh $RDMA $CLIENT $SERVER $BIN/rdma.zsh $RDMA $CLIENT $SERVER

43
run/cthon.zsh Executable file
View File

@ -0,0 +1,43 @@
#!/bin/zsh
zparseopts -D -K -server:=SERVER -export:=EXPORT -mountpoint:=MOUNTPOINT \
-user:=USER -proto:=PROTO -version+:=VERSION -mntopt+:=MOUNTOPTS \
b=TEST g=TEST s=TEST l=TEST
exclude=(--mntopt)
MOUNTOPTS=(${(ou)MOUNTOPTS:|exclude})
function runtest
{
./server ${TEST[-1]} -o $1 -m $2 -p $3 ${SERVER[-1]} > $4 2>&1
if [ $? -ne 0 ]; then
echo ""
echo "The '${TEST[-1]}' test using '$1' options to ${SERVER[-1]}: Failed!!"
mv $4 $4-`date +"%H:%M:%S"`.error
fi
if [ $(grep -c $2 /proc/mounts) -gt 0 ]; then
sudo umount $2
fi
}
cd cthon04
for vers in $VERSION; do
[[ "$vers" == "--version" ]] && continue
dir=$(echo "nfsv${vers}${PROTO[-1]}" | sed 's/\.//' | sed 's/v40/v4/')
mnt=${MOUNTPOINT[-1]}/$dir
xprt=${EXPORT[-1]}/${USER[-1]}/$dir
opts="v$vers,proto=${PROTO[-1]}"
for o in $MOUNTOPTS; do
opts="$opts,$o"
done
echo "./server ${TEST[-1]} -o $opts -m $mnt -p $xprt ${SERVER[-1]}"
runtest $opts $mnt $xprt /tmp/nfsv${vers}${PROTO[-1]} &
done
echo -n "Waiting for '${TEST[-1]}' to finish ... "
wait
echo -n "Done: "
date +"%X"

11
run/nfstest-rplus.zsh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/zsh
zparseopts -D -K -server:=SERVER -export:=EXPORT \
-mountpoint:=MOUNTPOINT -user:=USER
NFSTEST_DIR=/home/anna/nfstest
export PYTHONPATH=$NFSTEST_DIR
$NFSTEST_DIR/test/nfstest_rplus --server ${SERVER[-1]} \
--export ${EXPORT[-1]}/${USER[-1]}/nfsv42tcp \
--mtpoint ${MOUNTPOINT[-1]}/test/nfsv42tcp

View File

@ -8,23 +8,31 @@ zparseopts -D -K -server:=SERVER -opts:=OPTS -user:=USER \
xdir=$(echo "nfsv${VERSION[-1]}${PROTO[-1]}" | sed 's/\.//' | sed 's/v40/v4/') xdir=$(echo "nfsv${VERSION[-1]}${PROTO[-1]}" | sed 's/\.//' | sed 's/v40/v4/')
cd /home/${USER[-1]}/xfstests-dev cd /home/${USER[-1]}/xfstests-dev
export TEST_DEV=${SERVER[-1]}:${EXPORT[-1]}/${USER[-1]}/$xdir export TEST_DEV=$(echo ${SERVER[-1]}:${EXPORT[-1]}/${USER[-1]}/$xdir | sed 's|//|/|')
export TEST_DIR=${MOUNTPOINT[-1]}/$xdir export TEST_DIR=${MOUNTPOINT[-1]}/$xdir
export SCRATCH_DEV=${SERVER[-1]}:${SCRATCH[-1]}/${USER[-1]}/$xdir if [ "${SCRATCH[-1]}" != "NONE" ]; then
export SCRATCH_MNT=${SCRATCHMNT[-1]}/$xdir export SCRATCH_DEV=${SERVER[-1]}:${SCRATCH[-1]}/${USER[-1]}/$xdir
export SCRATCH_MNT=${SCRATCHMNT[-1]}/$xdir
fi
export NFS_MOUNT_OPTIONS="-o proto=${PROTO[-1]},v${VERSION[-1]},${OPTS[-1]}" export NFS_MOUNT_OPTIONS="-o proto=${PROTO[-1]},v${VERSION[-1]},${OPTS[-1]}"
export RESULT_BASE=/home/${USER[-1]}/xfstests-dev/results/${PROTO[-1]}/${VERSION[-1]} export RESULT_BASE=/home/${USER[-1]}/xfstests-dev/results/${PROTO[-1]}/${VERSION[-1]}
mkdir -p $TEST_DIR mkdir -p $TEST_DIR
mkdir -p $SCRATCH_MNT if [ "${SCRATCH[-1]}" != "NONE" ]; then
mkdir -p $SCRATCH_MNT
fi
[ -e local.config ] && rm -f local.config [ -e local.config ] && rm -f local.config
[ -e $RESULT_BASE/result.xml ] && rm -f $RESULT_BASE/result.xml [ -e $RESULT_BASE/result.xml ] && rm -f $RESULT_BASE/result.xml
echo "TIME -- $(date)" echo "TIME -- $(date)"
echo "TEST_DEV -- $TEST_DEV" echo "TEST_DEV -- $TEST_DEV"
echo "TEST_DIR -- $TEST_DIR" echo "TEST_DIR -- $TEST_DIR"
echo "SCRATCH_DEV -- $SCRATCH_DEV" if [ "${SCRATCH[-1]}" != "NONE" ]; then
echo "SCRATCH_MNT -- $SCRATCH_MNT" echo "SCRATCH_DEV -- $SCRATCH_DEV"
echo "SCRATCH_MNT -- $SCRATCH_MNT"
else
echo "SCRATCH_DEV -- NONE"
fi
echo "MOUNT_OPTIONS -- $NFS_MOUNT_OPTIONS" echo "MOUNT_OPTIONS -- $NFS_MOUNT_OPTIONS"
if [ ! -z "$*" ]; then if [ ! -z "$*" ]; then
@ -32,4 +40,3 @@ if [ ! -z "$*" ]; then
fi fi
./check -nfs -r -R xunit $* ./check -nfs -r -R xunit $*
#./check -nfs -R xunit $*

9
setup.zsh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/zsh
BIN=.local/bin
[[ "$(basename $0)" == "run.zsh" ]] && TARGET=$BIN/run || TARGET=$BIN/setup
TARGET=$TARGET/$1
shift
[[ -x $TARGET ]] && $TARGET $*

50
setup/read_plus-files.py Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/python -u
"""Create sparse files for testing with various patterns."""
import datetime
import pathlib
import os
import string
import sys
PAGE_SIZE = 4096
PAGE_HEADER = "<<<Start Of Page>>>\n"
PAGE_FOOTER = "\n<<<End Of Page>>>\n"
line = string.ascii_letters + string.digits + "\n"
data_len = PAGE_SIZE - len(PAGE_HEADER + PAGE_FOOTER)
(n_lines, n_chars) = divmod(data_len, len(line))
page_data = PAGE_HEADER + (line * n_lines) + line[:n_chars] + PAGE_FOOTER
PAGE_DATA = page_data.encode()
FILE_BASE = pathlib.Path(sys.argv[1])
FILE_SIZE = int(sys.argv[2])
FILE_SIZE_BYTES = FILE_SIZE * 1024 * 1024
FILE_N_PAGES = FILE_SIZE_BYTES // PAGE_SIZE
def allocate_testfile(name: str, n_pages: int, hole: bool) -> None:
"""Allocate a single test file."""
file = FILE_BASE / f"{FILE_SIZE}M-{name}"
if file.exists():
return
print(f"Allocating file: {file.stem} ...", end="")
start = datetime.datetime.now()
with open(file, 'wb') as f:
f.truncate(FILE_SIZE_BYTES)
for chunk in range(FILE_N_PAGES // n_pages):
if hole:
f.seek(PAGE_SIZE * n_pages, os.SEEK_CUR)
else:
f.write(PAGE_DATA * n_pages)
hole = not hole
os.fsync(f)
tdelta = datetime.datetime.now() - start
time = float(f"{tdelta.seconds}.{tdelta.microseconds}")
print(f" [Done: {round(time, 2):.2f}s]")
allocate_testfile("data", FILE_N_PAGES, False)
allocate_testfile("hole", FILE_N_PAGES, True)
for chunk in [int(c) for c in sys.argv[3].split(",")]:
allocate_testfile(f"mixed-{chunk}d", chunk, False)
allocate_testfile(f"mixed-{chunk}h", chunk, True)

22
setup/read_plus.zsh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/zsh
SERVER=$1
EXPORT=$2
MOUNTPOINT=$3/read_plus
USER=$4
SIZE=$5
CHUNKS=$6
if [ "$#" -ne 6 ]; then
echo "Usage: $0 {server} {export} {mountpoint} {user} {size} {chunks}"
exit 1
fi
mkdir -p $MOUNTPOINT
mount -o sec=sys $SERVER:$EXPORT $MOUNTPOINT
TRAPEXIT() {
sudo umount -f $MOUNTPOINT
}
mkdir -p -m 777 $MOUNTPOINT/$USER/read_plus
setup.zsh read_plus-files.py $MOUNTPOINT/$USER/read_plus $SIZE $CHUNKS
sync

View File

@ -1,4 +1,4 @@
#!/bin/zsh #!/bin/zsh -e
SERVER=$1 SERVER=$1
EXPORT=$2 EXPORT=$2
MOUNTPOINT=$3 MOUNTPOINT=$3

View File

@ -16,5 +16,7 @@ groupadd fsgqa 2>/dev/null
useradd --badnames 123456-fsgqa 2>/dev/null useradd --badnames 123456-fsgqa 2>/dev/null
useradd fsgqa2 2>/dev/null useradd fsgqa2 2>/dev/null
setup-testdirs.zsh $SERVER $EXPORT $MOUNTPOINT $USER setup.zsh testdirs.zsh $SERVER $EXPORT $MOUNTPOINT $USER
setup-testdirs.zsh $SERVER $SCRATCH $SCRATCHMNT $USER if [ "$SCRATCH" != "NONE" ]; then
setup.zsh testdirs.zsh $SERVER $SCRATCH $SCRATCHMNT $USER
fi

View File

@ -1,13 +0,0 @@
#!/bin/bash
FROM="--from=Anna.Schumaker@Netapp.com"
TO="--to=Trond.Myklebust@hammerspace.com"
#TO="--to=bfields@redhat.com --to=chuck.lever@oracle.com"
#TO="--to=fstests@vger.kernel.org"
#TO="--to=steved@redhat.com"
TO="$TO --to=linux-nfs@vger.kernel.org"
CC="--cc=Anna.Schumaker@Netapp.com"
git send-email $FROM $TO $CC $*

25
submit-patches.zsh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/zsh
zparseopts -D -K \
-nfs+=WHO -nfsd+=WHO -nfsutils+=WHO -xfstests+=WHO -fstests+=WHO \
-linus+=WHO
if [[ ${#WHO} -eq 0 ]]; then
echo "Who to submit to?"
exit 1
fi
TO=(--to=linux-nfs@vger.kernel.org)
for who in $WHO; do
case $who in
--nfs) TO+=(--to=trond.myklebust@hammerspace.com) ;;
--nfsd) TO+=(--to=chuck.lever@oracle.com) ;;
--nfsutils) TO+=(--to=steved@redhat.com) ;;
--linus) TO+=(--to=torvalds@linux-foundation.org) ;;
--xfstests | --fstests) TO+=(--to=fstests@vger.kernel.org) ;;
esac
done
TO+=(--cc=anna@kernel.org)
git send-email $TO $*

View File

@ -4,7 +4,7 @@
SERVER=cheesecake SERVER=cheesecake
# Music source # Music source
SOURCE=/net/cheesecake/srv/Media/Music/vorbis/ SOURCE=/net/cheesecake/media/Music/vorbis/
# Music directory / destination # Music directory / destination
MUSIC=/home/anna/Music MUSIC=/home/anna/Music

12
unlock-sqlite-db.zsh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/zsh
if [[ $# != 1 ]]; then
echo "Usage: $0 [FILE]"
exit 1
fi
backup="$(mktemp)"
mv $1 $backup
cp $backup $1
rm $backup

10
vm.zsh
View File

@ -33,12 +33,8 @@ function vm_reboot() {
vm_boot $1 vm_boot $1
} }
TRAPEXIT() { TRAPINT() {
if [[ ! -z "$(jobs -pr)" ]]; then kill -9 0
for job in ($(jobs -pr)); do
kill -9 $job
done
fi
} }
for vm in "${@:2}"; do for vm in "${@:2}"; do
@ -59,4 +55,4 @@ for vm in "${@:2}"; do
esac esac
done done
wait $(jobs -pr) wait

View File

@ -1,17 +1,16 @@
#!/bin/zsh -e #!/bin/zsh -e
CLIENT=(client) source common.zsh
SERVER=(server)
EXPORT=(/srv/test)
SCRATCH=(/srv/scratch)
MOUNTPOINT=(/mnt/test)
SCRATCHMNT=(/mnt/scratch)
VERSION=(3 4.0 4.1 4.2) VERSION=(3 4.0 4.1 4.2)
PROTO=(tcp) PROTO=(tcp)
GROUP=(-g quick)
zparseopts -D -K \ zparseopts -D -K \
c:=CLIENT -client:=CLIENT \ c:=CLIENT -client:=CLIENT \
g:=GROUP -group:=GROUP \
k:=SCRATCH -scratch:=SCRATCH \ k:=SCRATCH -scratch:=SCRATCH \
-nconnect:=NCONNECT \ -no-scratch=NO_SCRATCH \
-no-server-access=NO_SERVER_ACCESS \
o+:=MNTOPTS -options+:=MNTOPTS \
p:=MOUNTPOINT -mountpoint:=MOUNTPOINT \ p:=MOUNTPOINT -mountpoint:=MOUNTPOINT \
q:=SCRATCHMNT -scratchmnt:=SCRATCHMNT \ q:=SCRATCHMNT -scratchmnt:=SCRATCHMNT \
r:=RDMA -rdma:=RDMA \ r:=RDMA -rdma:=RDMA \
@ -19,11 +18,8 @@ zparseopts -D -K \
x:=EXPORT -export:=EXPORT \ x:=EXPORT -export:=EXPORT \
v+:=VERSION -version+:=VERSION v+:=VERSION -version+:=VERSION
BIN=$HOME/bin COLOR=$COLORS/xfstests.py
COLOR=$BIN/colors/xfstests.py OPTIONS="sec=sys$(echo $MNTOPTS | sed -E 's/ ?-o /,/g')"
RUN_XFSTESTS="sudo run-xfstests.zsh"
OPTIONS="sec=sys"
USER=$(whoami)
RESULT_BASE=$HOME/.local/share/xfstests/ RESULT_BASE=$HOME/.local/share/xfstests/
DATE=$(date +%Y-%m-%d-%H:%M:%S%z) DATE=$(date +%Y-%m-%d-%H:%M:%S%z)
TODAY=$(date +%Y/%m/%d) TODAY=$(date +%Y/%m/%d)
@ -39,52 +35,56 @@ fi
# #
# Prepare to test # Prepare to test
# #
$BIN/vm.zsh boot ${CLIENT[-1]} ${SERVER[-1]} function setup_client_func()
$BIN/install-scripts.zsh ${CLIENT[-1]} {
if [ ${#RDMA} -gt 0 ]; then client_setup xfstests.zsh ${SERVER[-1]} ${EXPORT[-1]} \
PROTO+=(rdma) ${MOUNTPOINT[-1]} ${SCRATCH[-1]} \
$BIN/rping.zsh ${RDMA[-1]} ${CLIENT[-1]} ${SERVER[-1]} ${SCRATCHMNT[-1]} $USER
fi }
if [ ${#NCONNECT} -gt 0 ]; then
OPTIONS="$OPTIONS,nconnect=${NCONNECT[-1]}"
fi
ssh ${CLIENT[-1]} "sudo setup-xfstests.zsh ${SERVER[-1]} ${EXPORT[-1]} ${MOUNTPOINT[-1]} \ prepare_to_test
${SCRATCH[-1]} ${SCRATCHMNT[-1]} $USER"
echo if [ ${#NO_SCRATCH} -gt 0 ]; then
SCRATCH+=("NONE")
fi
testargs=() testargs=()
for arg in $*; do for arg in $*; do
testargs+=($(printf '%q' "$arg")) testargs+=($(printf '%q' "$arg"))
GROUP=()
done done
run_xfs_tests() { run_xfs_tests() {
ssh ${CLIENT[-1]} "$RUN_XFSTESTS --server ${SERVER[-1]} \ for proto in $PROTO; do
--export ${EXPORT[-1]} \ client_run xfstests.zsh --server ${SERVER[-1]} \
--mountpoint ${MOUNTPOINT[-1]} \ --export ${EXPORT[-1]} \
--scratch ${SCRATCH[-1]} \ --mountpoint ${MOUNTPOINT[-1]} \
--scratchmnt ${SCRATCHMNT[-1]} \ --scratch ${SCRATCH[-1]} \
--proto $1 \ --scratchmnt ${SCRATCHMNT[-1]} \
--version $2 \ --proto $proto --version $1 \
--opts $OPTIONS \ --opts $OPTIONS \
--user $USER $testargs" | python $COLOR $1 $2 --user $USER $GROUP $testargs | python $COLOR $proto $1
scp -q ${CLIENT[-1]}:$REMOTE_RESULTS/$1/$2/result.xml $TMP_RESULTS/$1-$2.xml
if [[ "$proto" == "rdma" ]]; then
xunit="$TMP_RESULTS/${RDMA[-1]}-$1.xml"
else
xunit="$TMP_RESULTS/$proto-$1.xml"
fi
scp -q ${CLIENT[-1]}:$REMOTE_RESULTS/$proto/$1/result.xml $xunit
xfstestsdb xunit read $RUNID $xunit | python $COLOR $proto $1
done
} }
# #
# Run tests # Run tests
# #
mkdir -p $TMP_RESULTS mkdir -p $TMP_RESULTS
for proto in $PROTO; do RUNID=$(xfstestsdb new ${SERVER[-1]}:${EXPORT[-1]} | awk -F" | #" '{print $3}')
for vers in $VERSION; do for vers in $VERSION; do
case $vers in run_xfs_tests $vers &
"-v" | "--version") continue ;;
esac
run_xfs_tests $proto $vers &
done
done done
wait wait
mkdir -p $RESULTS mkdir -p $RESULTS
@ -92,5 +92,12 @@ tar -cJf $RESULTS/$NOW.tar.xz -C $(dirname $TMP_RESULTS) $NOW/
if [ ! -z "$TAG" ]; then if [ ! -z "$TAG" ]; then
mkdir -p $TAGRES mkdir -p $TAGRES
ln $RESULTS/$NOW.tar.xz $TAGRES/$DATE.tar.xz ln $RESULTS/$NOW.tar.xz $TAGRES/$DATE.tar.xz
xfstestsdb tag $RUNID $TAG
fi fi
optirun report-xfstests.py $RESULTS/$NOW.tar.xz & disown
echo
xfstestsdb xunit list --results --runid $RUNID
echo
xfstestsdb show --failure $RUNID
echo
report-xfstests.py $RESULTS/$NOW.tar.xz & disown