]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #!/usr/bin/env python |
2 | ||
3 | from subprocess import check_call, call, check_output, Popen, PIPE | |
4 | import re | |
5 | import sys | |
6 | import signal | |
7 | ||
8 | fio_template = """ | |
9 | [global] | |
10 | thread=1 | |
11 | invalidate=1 | |
12 | rw=%(testtype)s | |
13 | time_based=1 | |
14 | runtime=%(runtime)s | |
15 | ioengine=libaio | |
16 | direct=1 | |
17 | bs=%(blocksize)d | |
18 | iodepth=%(iodepth)d | |
19 | %(verify)s | |
20 | verify_dump=1 | |
21 | ||
22 | """ | |
23 | ||
24 | verify_template = """ | |
25 | do_verify=1 | |
26 | verify=meta | |
27 | verify_pattern="meta" | |
28 | """ | |
29 | ||
30 | ||
31 | fio_job_template = """ | |
32 | [job%(jobnumber)d] | |
33 | filename=%(device)s | |
34 | ||
35 | """ | |
36 | ||
37 | def interrupt_handler(signum, frame): | |
38 | fio.terminate() | |
39 | print "FIO terminated" | |
40 | sys.exit(0) | |
41 | ||
42 | def main(): | |
43 | ||
44 | global fio | |
45 | if (len(sys.argv) < 5): | |
46 | print "usage:" | |
47 | print " " + sys.argv[0] + " <io_size> <queue_depth> <test_type> <runtime>" | |
48 | print "advanced usage:" | |
49 | print "If you want to run fio with verify, please add verify string after runtime." | |
50 | print "Currently fio.py only support write rw randwrite randrw with verify enabled." | |
51 | sys.exit(1) | |
52 | ||
53 | io_size = int(sys.argv[1]) | |
54 | queue_depth = int(sys.argv[2]) | |
55 | test_type = sys.argv[3] | |
56 | runtime = sys.argv[4] | |
57 | if len(sys.argv) > 5: | |
58 | verify = True | |
59 | else: | |
60 | verify = False | |
61 | ||
62 | devices = get_target_devices() | |
63 | print "Found devices: ", devices | |
64 | ||
65 | # configure_devices(devices) | |
66 | fio_executable = '/usr/bin/fio' | |
67 | ||
68 | device_paths = ['/dev/' + dev for dev in devices] | |
69 | print device_paths | |
70 | sys.stdout.flush() | |
71 | signal.signal(signal.SIGTERM, interrupt_handler) | |
72 | signal.signal(signal.SIGINT, interrupt_handler) | |
73 | fio = Popen([fio_executable, '-'], stdin=PIPE) | |
74 | fio.communicate(create_fio_config(io_size, queue_depth, device_paths, test_type, runtime, verify)) | |
75 | fio.stdin.close() | |
76 | rc = fio.wait() | |
77 | print "FIO completed with code %d\n" % rc | |
78 | sys.stdout.flush() | |
79 | sys.exit(rc) | |
80 | ||
81 | def get_target_devices(): | |
82 | output = check_output('lsblk -l -o NAME', shell=True) | |
83 | return re.findall("(nvme[0-9]+n[0-9]+)\n", output) | |
84 | ||
85 | def create_fio_config(size, q_depth, devices, test, run_time, verify): | |
86 | if not verify: | |
87 | verifyfio = "" | |
88 | else: | |
89 | verifyfio = verify_template | |
90 | fiofile = fio_template % {"blocksize": size, "iodepth": q_depth, | |
91 | "testtype": test, "runtime": run_time, "verify": verifyfio} | |
92 | for (i, dev) in enumerate(devices): | |
93 | fiofile += fio_job_template % {"jobnumber": i, "device": dev} | |
94 | return fiofile | |
95 | ||
96 | def set_device_parameter(devices, filename_template, value): | |
97 | for dev in devices: | |
98 | filename = filename_template % dev | |
99 | f = open(filename, 'r+b') | |
100 | f.write(value) | |
101 | f.close() | |
102 | ||
103 | def configure_devices(devices): | |
104 | set_device_parameter(devices, "/sys/block/%s/queue/nomerges", "2") | |
105 | set_device_parameter(devices, "/sys/block/%s/queue/nr_requests", "128") | |
106 | requested_qd = 128 | |
107 | qd = requested_qd | |
108 | while qd > 0: | |
109 | try: | |
110 | set_device_parameter(devices, "/sys/block/%s/device/queue_depth", str(qd)) | |
111 | break | |
112 | except IOError: | |
113 | qd = qd - 1 | |
114 | if qd == 0: | |
115 | print "Could not set block device queue depths." | |
116 | else: | |
117 | print "Requested queue_depth {} but only {} is supported.".format(str(requested_qd), str(qd)) | |
118 | set_device_parameter(devices, "/sys/block/%s/queue/scheduler", "noop") | |
119 | ||
120 | if __name__ == "__main__": | |
121 | main() |