X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=t%2Fstrided.py;h=aac15d10ac1f6c8b40f07d14acd06cdbab17d7f6;hb=HEAD;hp=c159dc0b61bc307b0160bae8389c90cacf53445c;hpb=cc16261082a4d0f027cef9d019ad023129bf6012;p=fio.git diff --git a/t/strided.py b/t/strided.py index c159dc0b..75c429e4 100755 --- a/t/strided.py +++ b/t/strided.py @@ -1,12 +1,12 @@ -#!/usr/bin/python -# Note: this script is python2 and python3 compatible. -# +#!/usr/bin/env python3 + +""" # strided.py # # Test zonemode=strided. This uses the null ioengine when no file is # specified. If a file is specified, use it for randdom read testing. # Some of the zoneranges in the tests are 16MiB. So when using a file -# a minimum size of 32MiB is recommended. +# a minimum size of 64MiB is recommended. # # USAGE # python strided.py fio-executable [-f file/device] @@ -14,337 +14,431 @@ # EXAMPLES # python t/strided.py ./fio # python t/strided.py ./fio -f /dev/sda -# dd if=/dev/zero of=temp bs=1M count=32 +# dd if=/dev/zero of=temp bs=1M count=64 # python t/strided.py ./fio -f temp # -# REQUIREMENTS -# Python 2.6+ -# # ===TEST MATRIX=== # -# --zonemode=strided, zoneskip >= 0 +# --zonemode=strided, zoneskip unset # w/ randommap and LFSR # zonesize=zonerange all blocks in zonerange touched # zonesize>zonerange all blocks touched and roll-over back into zone # zonesize= test['filesize']: - zonestart = 0 if 'offset' not in test else test['offset'] - - iosperzone = iosperzone + 1 - tokens = line.split(',') - offset = int(tokens[4]) - if offset < zonestart or offset >= zonestart + test['zonerange']: - print("Offset {0} outside of zone starting at {1}".format( - offset, zonestart)) - return False - - # skip next section if norandommap is enabled with no - # random_generator or with a random_generator != lfsr - if 'norandommap' in test: - if 'random_generator' in test: - if test['random_generator'] != 'lfsr': - continue - else: + if 'filename' in self.fio_opts: + for opt in ['filename', 'filesize']: + option = f"--{opt}={self.fio_opts[opt]}" + fio_args.append(option) + else: + fio_args.append('--ioengine=null') + for opt in ['size', 'io_size', 'filesize']: + option = f"--{opt}={self.fio_opts[opt]}" + fio_args.append(option) + + super().setup(fio_args) + + def check_result(self): + super().check_result() + if not self.passed: + return + + zonestart = 0 if 'offset' not in self.fio_opts else self.fio_opts['offset'] + iospersize = self.fio_opts['zonesize'] / self.fio_opts['bs'] + iosperrange = self.fio_opts['zonerange'] / self.fio_opts['bs'] + iosperzone = 0 + lines = self.iops_log_lines.split('\n') + zoneset = set() + + for line in lines: + if len(line) == 0: continue - # we either have a random map enabled or we - # are using an LFSR - # so all blocks should be unique and we should have - # covered the entire zone when iosperzone % iosperrange == 0 - block = (offset - zonestart) / test['bs'] - if block in zoneset: - print("Offset {0} in zone already touched".format(offset)) - return False + if iosperzone == iospersize: + # time to move to a new zone + iosperzone = 0 + zoneset = set() + zonestart += self.fio_opts['zonerange'] + if zonestart >= self.fio_opts['filesize']: + zonestart = 0 if 'offset' not in self.fio_opts else self.fio_opts['offset'] - zoneset.add(block) - if iosperzone % iosperrange == 0: - if len(zoneset) != iosperrange: - print("Expected {0} blocks in zone but only saw {1}".format( - iosperrange, len(zoneset))) - return False - zoneset = set() + iosperzone = iosperzone + 1 + tokens = line.split(',') + offset = int(tokens[4]) + if offset < zonestart or offset >= zonestart + self.fio_opts['zonerange']: + print(f"Offset {offset} outside of zone starting at {zonestart}") + return - return True + # skip next section if norandommap is enabled with no + # random_generator or with a random_generator != lfsr + if 'norandommap' in self.fio_opts: + if 'random_generator' in self.fio_opts: + if self.fio_opts['random_generator'] != 'lfsr': + continue + else: + continue + # we either have a random map enabled or we + # are using an LFSR + # so all blocks should be unique and we should have + # covered the entire zone when iosperzone % iosperrange == 0 + block = (offset - zonestart) / self.fio_opts['bs'] + if block in zoneset: + print(f"Offset {offset} in zone already touched") + return + + zoneset.add(block) + if iosperzone % iosperrange == 0: + if len(zoneset) != iosperrange: + print(f"Expected {iosperrange} blocks in zone but only saw {len(zoneset)}") + return + zoneset = set() + + +TEST_LIST = [ # randommap enabled + { + "test_id": 1, + "fio_opts": { + "zonerange": 4096, + "zonesize": 4096, + "bs": 4096, + "offset": 8*4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 2, + "fio_opts": { + "zonerange": 4096, + "zonesize": 4096, + "bs": 4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 3, + "fio_opts": { + "zonerange": 16*1024*1024, + "zonesize": 16*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + { + "test_id": 4, + "fio_opts": { + "zonerange": 4096, + "zonesize": 4*4096, + "bs": 4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 5, + "fio_opts": { + "zonerange": 16*1024*1024, + "zonesize": 32*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + { + "test_id": 6, + "fio_opts": { + "zonerange": 8192, + "zonesize": 4096, + "bs": 4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 7, + "fio_opts": { + "zonerange": 16*1024*1024, + "zonesize": 8*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + # lfsr + { + "test_id": 8, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 4096*1024, + "zonesize": 4096*1024, + "bs": 4096, + "offset": 8*4096*1024, + "size": 16*4096*1024, + "io_size": 16*4096*1024, + }, + "test_class": StridedTest, + }, + { + "test_id": 9, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 4096*1024, + "zonesize": 4096*1024, + "bs": 4096, + "size": 16*4096*1024, + "io_size": 16*4096*1024, + }, + "test_class": StridedTest, + }, + { + "test_id": 10, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 16*1024*1024, + "zonesize": 16*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + { + "test_id": 11, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 4096*1024, + "zonesize": 4*4096*1024, + "bs": 4096, + "size": 16*4096*1024, + "io_size": 16*4096*1024, + }, + "test_class": StridedTest, + }, + { + "test_id": 12, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 16*1024*1024, + "zonesize": 32*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + { + "test_id": 13, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 8192*1024, + "zonesize": 4096*1024, + "bs": 4096, + "size": 16*4096*1024, + "io_size": 16*4096*1024, + }, + "test_class": StridedTest, + }, + { + "test_id": 14, + "fio_opts": { + "random_generator": "lfsr", + "zonerange": 16*1024*1024, + "zonesize": 8*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + # norandommap + { + "test_id": 15, + "fio_opts": { + "norandommap": 1, + "zonerange": 4096, + "zonesize": 4096, + "bs": 4096, + "offset": 8*4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 16, + "fio_opts": { + "norandommap": 1, + "zonerange": 4096, + "zonesize": 4096, + "bs": 4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 17, + "fio_opts": { + "norandommap": 1, + "zonerange": 16*1024*1024, + "zonesize": 16*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + { + "test_id": 18, + "fio_opts": { + "norandommap": 1, + "zonerange": 4096, + "zonesize": 8192, + "bs": 4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 19, + "fio_opts": { + "norandommap": 1, + "zonerange": 16*1024*1024, + "zonesize": 32*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*204, + }, + "test_class": StridedTest, + }, + { + "test_id": 20, + "fio_opts": { + "norandommap": 1, + "zonerange": 8192, + "zonesize": 4096, + "bs": 4096, + "size": 16*4096, + "io_size": 16*4096, + }, + "test_class": StridedTest, + }, + { + "test_id": 21, + "fio_opts": { + "norandommap": 1, + "zonerange": 16*1024*1024, + "zonesize": 8*1024*1024, + "bs": 4096, + "size": 256*1024*1024, + "io_size": 256*1024*1024, + }, + "test_class": StridedTest, + }, +] + + +def parse_args(): + """Parse command-line arguments.""" + + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--fio', help='path to file executable (e.g., ./fio)') + parser.add_argument('-a', '--artifact-root', help='artifact root directory') + parser.add_argument('-s', '--skip', nargs='+', type=int, + help='list of test(s) to skip') + parser.add_argument('-o', '--run-only', nargs='+', type=int, + help='list of test(s) to run, skipping all others') + parser.add_argument('--dut', + help='target file/device to test.') + args = parser.parse_args() + + return args + + +def main(): + """Run zonemode=strided tests.""" -if __name__ == '__main__': args = parse_args() - tests = [ # randommap enabled - { - "zonerange": 4096, - "zonesize": 4096, - "bs": 4096, - "offset": 8*4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "zonerange": 4096, - "zonesize": 4096, - "bs": 4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "zonerange": 16*1024*1024, - "zonesize": 16*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - { - "zonerange": 4096, - "zonesize": 4*4096, - "bs": 4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "zonerange": 16*1024*1024, - "zonesize": 32*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - { - "zonerange": 8192, - "zonesize": 4096, - "bs": 4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "zonerange": 16*1024*1024, - "zonesize": 8*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - # lfsr - { - "random_generator": "lfsr", - "zonerange": 4096*1024, - "zonesize": 4096*1024, - "bs": 4096, - "offset": 8*4096*1024, - "size": 16*4096*1024, - "io_size": 16*4096*1024, - }, - { - "random_generator": "lfsr", - "zonerange": 4096*1024, - "zonesize": 4096*1024, - "bs": 4096, - "size": 16*4096*1024, - "io_size": 16*4096*1024, - }, - { - "random_generator": "lfsr", - "zonerange": 16*1024*1024, - "zonesize": 16*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - { - "random_generator": "lfsr", - "zonerange": 4096*1024, - "zonesize": 4*4096*1024, - "bs": 4096, - "size": 16*4096*1024, - "io_size": 16*4096*1024, - }, - { - "random_generator": "lfsr", - "zonerange": 16*1024*1024, - "zonesize": 32*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - { - "random_generator": "lfsr", - "zonerange": 8192*1024, - "zonesize": 4096*1024, - "bs": 4096, - "size": 16*4096*1024, - "io_size": 16*4096*1024, - }, - { - "random_generator": "lfsr", - "zonerange": 16*1024*1024, - "zonesize": 8*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - # norandommap - { - "norandommap": 1, - "zonerange": 4096, - "zonesize": 4096, - "bs": 4096, - "offset": 8*4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "norandommap": 1, - "zonerange": 4096, - "zonesize": 4096, - "bs": 4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "norandommap": 1, - "zonerange": 16*1024*1024, - "zonesize": 16*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - { - "norandommap": 1, - "zonerange": 4096, - "zonesize": 8192, - "bs": 4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "norandommap": 1, - "zonerange": 16*1024*1024, - "zonesize": 32*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*204, - }, - { - "norandommap": 1, - "zonerange": 8192, - "zonesize": 4096, - "bs": 4096, - "size": 16*4096, - "io_size": 16*4096, - }, - { - "norandommap": 1, - "zonerange": 16*1024*1024, - "zonesize": 8*1024*1024, - "bs": 4096, - "size": 256*1024*1024, - "io_size": 256*1024*1024, - }, - - ] - - index = 1 - passed = 0 - failed = 0 - - if args.filename: - statinfo = os.stat(args.filename) + artifact_root = args.artifact_root if args.artifact_root else \ + f"strided-test-{time.strftime('%Y%m%d-%H%M%S')}" + os.mkdir(artifact_root) + print(f"Artifact directory is {artifact_root}") + + if args.fio: + fio_path = str(Path(args.fio).absolute()) + else: + fio_path = 'fio' + print(f"fio path is {fio_path}") + + if args.dut: + statinfo = os.stat(args.dut) filesize = statinfo.st_size if filesize == 0: - f = os.open(args.filename, os.O_RDONLY) + f = os.open(args.dut, os.O_RDONLY) filesize = os.lseek(f, 0, os.SEEK_END) os.close(f) - for test in tests: - if args.filename: - test['filename'] = args.filename - test['filesize'] = filesize + for test in TEST_LIST: + if args.dut: + test['fio_opts']['filename'] = os.path.abspath(args.dut) + test['fio_opts']['filesize'] = filesize else: - test['filesize'] = test['size'] - iops_log = run_fio(args.fio, test, index) - status = check_output(iops_log, test) - print("Test {0} {1}".format(index, ("PASSED" if status else "FAILED"))) - if status: - passed = passed + 1 - else: - failed = failed + 1 - index = index + 1 + test['fio_opts']['filesize'] = test['fio_opts']['size'] - print("{0} tests passed, {1} failed".format(passed, failed)) + test_env = { + 'fio_path': fio_path, + 'fio_root': str(Path(__file__).absolute().parent.parent), + 'artifact_root': artifact_root, + 'basename': 'strided', + } + _, failed, _ = run_fio_tests(TEST_LIST, test_env, args) sys.exit(failed) + + +if __name__ == '__main__': + main()