Commit 723977ca authored by Ming Lei's avatar Ming Lei Committed by Jens Axboe
Browse files

selftests: ublk: add generic_01 for verifying sequential IO order



block layer, ublk and io_uring might re-order IO in the past

- plug

- queue ublk io command via task work

Add one test for verifying if sequential WRITE IO is dispatched in order.

- null target is taken, so we can just observe io order from
`tracepoint:block:block_rq_complete` which represents the dispatch order

- WRITE IO is taken because READ may come from system-wide utility

Cc: Uday Shankar <ushankar@purestorage.com>
Signed-off-by: default avatarMing Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250322093218.431419-2-ming.lei@redhat.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ffde32a4
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -3,7 +3,9 @@
CFLAGS += -O3 -Wl,-no-as-needed -Wall -I $(top_srcdir)
LDLIBS += -lpthread -lm -luring

TEST_PROGS := test_null_01.sh
TEST_PROGS := test_generic_01.sh

TEST_PROGS += test_null_01.sh
TEST_PROGS += test_loop_01.sh
TEST_PROGS += test_loop_02.sh
TEST_PROGS += test_loop_03.sh
+22 −0
Original line number Diff line number Diff line
@@ -3,6 +3,26 @@

UBLK_SKIP_CODE=4

_have_program() {
	if command -v "$1" >/dev/null 2>&1; then
		return 0
	fi
	return 1
}

_get_disk_dev_t() {
	local dev_id=$1
	local dev
	local major
	local minor

	dev=/dev/ublkb"${dev_id}"
	major=$(stat -c '%Hr' "$dev")
	minor=$(stat -c '%Lr' "$dev")

	echo $(( (major & 0xfff) << 20 | (minor & 0xfffff) ))
}

_create_backfile() {
	local my_size=$1
	local my_file
@@ -121,6 +141,7 @@ _check_add_dev()

_cleanup_test() {
	"${UBLK_PROG}" del -a
	rm -f "$UBLK_TMP"
}

_have_feature()
@@ -216,6 +237,7 @@ _ublk_test_top_dir()
	cd "$(dirname "$0")" && pwd
}

UBLK_TMP=$(mktemp ublk_test_XXXXX)
UBLK_PROG=$(_ublk_test_top_dir)/kublk
UBLK_TEST_QUIET=1
UBLK_TEST_SHOW_RESULT=1
+44 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh

TID="generic_01"
ERR_CODE=0

if ! _have_program bpftrace; then
	exit "$UBLK_SKIP_CODE"
fi

_prep_test "null" "sequential io order"

dev_id=$(_add_ublk_dev -t null)
_check_add_dev $TID $?

dev_t=$(_get_disk_dev_t "$dev_id")
bpftrace trace/seq_io.bt "$dev_t" "W" 1 > "$UBLK_TMP" 2>&1 &
btrace_pid=$!
sleep 2

if ! kill -0 "$btrace_pid" > /dev/null 2>&1; then
	_cleanup_test "null"
	exit "$UBLK_SKIP_CODE"
fi

# run fio over this ublk disk
fio --name=write_seq \
    --filename=/dev/ublkb"${dev_id}" \
    --ioengine=libaio --iodepth=16 \
    --rw=write \
    --size=512M \
    --direct=1 \
    --bs=4k > /dev/null 2>&1
ERR_CODE=$?
kill "$btrace_pid"
wait
if grep -q "io_out_of_order" "$UBLK_TMP"; then
	cat "$UBLK_TMP"
	ERR_CODE=255
fi
_cleanup_test "null"
_show_result $TID $ERR_CODE
+25 −0
Original line number Diff line number Diff line
/*
	$1: 	dev_t
	$2: 	RWBS
	$3:     strlen($2)
*/
BEGIN {
	@last_rw[$1, str($2)] = 0;
}
tracepoint:block:block_rq_complete
{
	$dev = $1;
	if ((int64)args.dev == $1 && !strncmp(args.rwbs, str($2), $3)) {
		$last = @last_rw[$dev, str($2)];
		if ((uint64)args.sector != $last) {
			printf("io_out_of_order: exp %llu actual %llu\n",
				args.sector, $last);
		}
		@last_rw[$dev, str($2)] = (args.sector + args.nr_sector);
	}
	@ios = count();
}

END {
	clear(@last_rw);
}