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