#!/usr/bin/python # Note: this script is python2 and python3 compatible. # # 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. # # USAGE # python strided.py fio-executable [-f file/device] # # EXAMPLES # python t/strided.py ./fio # python t/strided.py ./fio -f /dev/sda # dd if=/dev/zero of=temp bs=1M count=32 # python t/strided.py ./fio -f temp # # REQUIREMENTS # Python 2.6+ # # ===TEST MATRIX=== # # --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: 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 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() return True 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) filesize = statinfo.st_size if filesize == 0: f = os.open(args.filename, 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 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 print("{0} tests passed, {1} failed".format(passed, failed)) sys.exit(failed)