Skip to content

Commit

Permalink
Add fio-libblkio test
Browse files Browse the repository at this point in the history
libblkio requires extra setup, let's add it similarly to the nbd test.

Signed-off-by: Lukáš Doktor <[email protected]>
  • Loading branch information
ldoktor committed Dec 20, 2022
1 parent fff278c commit 31e4469
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 2 deletions.
9 changes: 8 additions & 1 deletion docs/source/scripts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,12 +198,19 @@ running via Run-perf as it might lead to unpredictable consequences.
Fio-nbd
-------

This is a special case of :ref:`test-fio` test but it is spawning qemu-nbd
This is a special case of :ref:`test-fio` test which is spawning qemu-nbd
export on each worker and tests the speed of the exported device. You can
still tweak various params (like type, ...) but note that the ``targets``,
``numjobs`` and ``job-file`` should be set automatically to suit the
configuration.

Fio-libblkio
------------

This is a special case of :ref:`test-fio` test which is using
qemu-storage-daemon and libblkio to utilize it's functions. It comes
with a custom job-file, but it allows tweaking.

Uperf
-----

Expand Down
35 changes: 35 additions & 0 deletions runperf/assets/pbench/libblkio.fio
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# To use fio to test libblkio:
#
# # Setup ramdisk (if needed)
# modprobe brd rd_nr=1 rd_size=1048576 max_part=0
#
# qemu-storage-daemon \
# --blockdev driver=host_device,node-name=file,filename=/dev/ram0,cache.direct=on \
# --object iothread,id=iothread0 \
# --export type=vhost-user-blk,iothread=iothread0,id=export,node-name=file,addr.type=unix,addr.path=vhost-user-blk.sock,writable=on
# fio libblkio.fio
# killall qemu-storage-daemon

[global]
bs=$@
ioengine=libblkio
libblkio_driver=virtio-blk-vhost-user
libblkio_path=/var/lib/runperf/runperf-libblkio/vhost-user-blk.sock
rw=$@
iodepth=1
hipri=%s # Can not be set by pbench-fio, use 0 or 1
direct=1
sync=0
time_based=1
clocksource=gettimeofday
ramp_time=5
runtime=10
write_bw_log=fio
write_iops_log=fio
write_lat_log=fio
log_avg_msec=1000
write_hist_log=fio
log_hist_msec=10000
# log_hist_coarseness=4 # 76 bins

[job0]
91 changes: 91 additions & 0 deletions runperf/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,97 @@ def cleanup(self):
PBenchFio.cleanup(self)


class PBenchLibblkio(PBenchFio):
"""
Executes PBenchFio with a custom job to test libblkio
By default it creates and distributes the job-file using "libblkio.fio"
from assets but you can override the job-file path and distribute your
own version. In such case you have to make sure to use the right paths
and format.
On top of the default params it also supports:
* hipri - sets corresponding fio option in the file (single value 0 or 1)
* target - changes the exported target path (by default /dev/ram0)
* __SETUP_RAMDISK__ - whether to setup ramdisk by "modprobe brd ..."
* __STORAGE_DAEMON_CMD__ - override the usual "qemu-storage-daemon" cmd
(you have to use %s as the target filename to be replaced here)
"""

name = "fio-libblkio"
default_args = (("numjobs", 1),
("job-file", "/var/lib/runperf/runperf-libblkio/"
"libblkio.fio"))
base_path = "/var/lib/runperf/runperf-libblkio/"

def __init__(self, host, workers, base_output_path, metadata, extra):
self._params = {}
self._params["hipri"] = extra.pop("hipri", 0)
self._params["target"] = extra.pop("target", "/dev/ram0")
self._params["setup_ramdisk"] = extra.pop("__SETUP_RAMDISK__", True)
socket_path = os.path.join(self.base_path, "vhost-user-blk.sock")
storage_daemon_cmd = extra.pop(
"__STORAGE_DAEMON_CMD__", "qemu-storage-daemon --blockdev "
"driver=host_device,node-name=file,filename=%s,cache.direct=on "
"--object iothread,id=iothread0 "
"--export type=vhost-user-blk,iothread=iothread0,id=export,"
"node-name=file,addr.type=unix,addr.path=%s,"
"writable=on")
try:
self._params["storage_daemon_cmd"] = (storage_daemon_cmd
% (self._params["target"],
socket_path))
except TypeError as details:
raise exceptions.TestSkip("Failed to format __STORAGE_DAEMON_CMD__"
"; expecting 2 %s (target and socket)"
% details)
self.fio_job_file = extra.get("job-file", self.base_path +
"libblkio.fio")
super().__init__(host, workers, base_output_path, metadata, extra)

def setup(self):
PBenchFio.setup(self)
with open(os.path.join(os.path.dirname(__file__), "assets", "pbench",
"libblkio.fio"),
encoding="utf-8") as fio:
fio_tpl = utils.shell_write_content_cmd(
self.fio_job_file, fio.read() % self._params["hipri"])
for workers in self.workers:
for worker in workers:
with worker.get_session_cont() as session:
session.runperf_stage("Start libblkio export")
if self._params.get("setup_ramdisk"):
session.cmd("modprobe brd rd_nr=1 rd_size=1048576 "
"max_part=0")
session.cmd("mkdir -p " + self.base_path)
session.cmd(f"nohup {self._params['storage_daemon_cmd']} "
"&> "
f"$(mktemp {self.base_path}/libblkio_XXXX.log)"
f" & echo $! >> {self.base_path}/kill_pids")
# Sometimes nohup is not enough, use disown
session.cmd(f"for PID in $(cat {self.base_path}/kill_pids)"
"; do disown -h $PID; done")
with self.host.get_session_cont(hop=self.host) as session:
session.cmd("mkdir -p " + self.base_path)
session.cmd(fio_tpl)

def cleanup(self):
for workers in self.workers:
for worker in workers:
with worker.get_session_cont() as session:
pids = session.cmd(f"cat {self.base_path}/kill_pids "
"2>/dev/null || true")
for pid in pids.splitlines():
session.cmd_status(f"kill -9 '{pid}'")
if self._params.get("setup_ramdisk"):
session.cmd_status("rmmod brd")
session.cmd("rm -Rf " + self.base_path)
with self.host.get_session_cont(hop=self.host) as session:
session.cmd(f"rm -Rf {self.base_path}")
PBenchFio.cleanup(self)


def get(name, extra):
"""
Get list of test classes based on test name
Expand Down
65 changes: 65 additions & 0 deletions selftests/core/test_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,71 @@ def test_custom_name(self):
self.assertTrue(os.path.exists(os.path.join(
self.tmpdir, "Custom_name")), os.listdir(self.tmpdir))

def test_libblkio(self):
tst = self.check(tests.PBenchLibblkio, {}, {"target": "/dev/other"},
'pbench-fio --job-file=/var/lib/runperf/'
'runperf-libblkio/libblkio.fio --numjobs=1 '
'--clients=addr2')
# Ensure proper setup
self.check_calls(
tst.host.mock_session.method_calls,
['cat > /var/lib/runperf/runperf-libblkio/libblkio.fio <<',
'libblkio_driver=virtio-blk-vhost-user',
'iodepth=1',
'hipri=0',
'pbench-fio',
'rm -Rf /var/lib/runperf/runperf-libblkio'])
self.check_calls(
tst.workers[0][0].mock_session.method_calls,
['modprobe brd rd_nr=1 rd_size=1048576 max_part=0',
'mkdir -p /var/lib/runperf/runperf-libblkio/',
'nohup qemu-storage-daemon --blockdev driver=host_device,' +
'node-name=file,filename=/dev/other,cache.direct=on --object' +
' iothread,id=iothread0 --export type=vhost-user-blk,' +
'iothread=iothread0,id=export,node-name=file,addr.type=unix,' +
'addr.path=/var/lib/runperf/runperf-libblkio/' +
'vhost-user-blk.sock,writable=on &> $(mktemp ' +
'/var/lib/runperf/runperf-libblkio//libblkio_XXXX.log) ' +
'& echo $! >> /var/lib/runperf/runperf-libblkio//kill_pids',
'for PID in $(cat /var/lib/runperf/runperf-libblkio' +
'//kill_pids); do disown -h $PID; done',
'cat /var/lib/runperf/runperf-libblkio//kill_pids' +
' 2>/dev/null || true',
'rmmod brd'])

def test_libblkio_custom(self):
tst = self.check(tests.PBenchLibblkio, {},
{"hipri": 1, "target": "/dev/sdb",
"__SETUP_RAMDISK__": False,
"__STORAGE_DAEMON_CMD__": "target %s socket %s"},
'pbench-fio --job-file=/var/lib/runperf/'
'runperf-libblkio/libblkio.fio --numjobs=1 '
'--clients=addr2')
# Ensure proper setup
self.check_calls(
tst.host.mock_session.method_calls,
['cat > /var/lib/runperf/runperf-libblkio/libblkio.fio <<',
'libblkio_driver=virtio-blk-vhost-user',
'iodepth=1',
'hipri=1',
'pbench-fio',
'rm -Rf /var/lib/runperf/runperf-libblkio'])
self.check_calls(
tst.workers[0][0].mock_session.method_calls,
['mkdir -p /var/lib/runperf/runperf-libblkio/',
'nohup target /dev/sdb socket /var/lib/runperf/runperf-' +
'libblkio/vhost-user-blk.sock &> $(mktemp /var/lib/runperf' +
'/runperf-libblkio//libblkio_XXXX.log) & echo $! >> ' +
'/var/lib/runperf/runperf-libblkio//kill_pids',
'for PID in $(cat /var/lib/runperf/runperf-libblkio' +
'//kill_pids); do disown -h $PID; done',
'cat /var/lib/runperf/runperf-libblkio//kill_pids' +
' 2>/dev/null || true'])
for call in tst.workers[0][0].mock_session.method_calls:
call = str(call)
for key in ('modprobe brd', 'rmmod brd'):
self.assertNotIn(key, call)


if __name__ == '__main__':
unittest.main()
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ def get_long_description():
'50PBenchFio = runperf.tests:PBenchFio',
'50Linpack = runperf.tests:Linpack',
'50UPerf = runperf.tests:UPerf',
'50PBenchNBD = runperf.tests:PBenchNBD'],
'50PBenchNBD = runperf.tests:PBenchNBD',
'50PBenchLibblkio = runperf.tests:PBenchLibblkio'],
'runperf.machine.distro_info': [
'50get_distro_info = runperf.machine:get_distro_info'],
'runperf.utils.cloud_image_providers': [
Expand Down

0 comments on commit 31e4469

Please sign in to comment.