One io command can be queued in split way, add test case for covering this way: - split the io command into two sub-io if the io size is bigger than 512 - the 1st sub-io size is 512byte, and the 2nd sub-io is the remained bytes Complete the whole io command until the two sub-io are queued. Signed-off-by: Ming Lei <tom.leiming@xxxxxxxxx> --- tools/testing/selftests/ublk/Makefile | 1 + .../testing/selftests/ublk/progs/ublk_null.c | 46 +++++++++++++++++++ tools/testing/selftests/ublk/test_null_03.sh | 21 +++++++++ 3 files changed, 68 insertions(+) create mode 100755 tools/testing/selftests/ublk/test_null_03.sh diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile index a95f317211e7..5a940bae9cbb 100644 --- a/tools/testing/selftests/ublk/Makefile +++ b/tools/testing/selftests/ublk/Makefile @@ -21,6 +21,7 @@ endif TEST_PROGS := test_null_01.sh TEST_PROGS += test_null_02.sh +TEST_PROGS += test_null_03.sh # Order correspond to 'make run_tests' order TEST_GEN_PROGS_EXTENDED = ublk_bpf diff --git a/tools/testing/selftests/ublk/progs/ublk_null.c b/tools/testing/selftests/ublk/progs/ublk_null.c index 3225b52dcd24..523bf8ff3ef8 100644 --- a/tools/testing/selftests/ublk/progs/ublk_null.c +++ b/tools/testing/selftests/ublk/progs/ublk_null.c @@ -11,6 +11,40 @@ /* libbpf v1.4.5 is required for struct_ops to work */ +static inline ublk_bpf_return_t __ublk_null_handle_io_split(const struct ublk_bpf_io *io, unsigned int _off) +{ + unsigned long off = -1, sects = -1; + const struct ublksrv_io_desc *iod; + int res; + + iod = ublk_bpf_get_iod(io); + if (iod) { + res = iod->nr_sectors << 9; + off = iod->start_sector; + sects = iod->nr_sectors; + } else + res = -EINVAL; + + BPF_DBG("ublk dev %u qid %u: handle io tag %u %lx-%d res %d", + ublk_bpf_get_dev_id(io), + ublk_bpf_get_queue_id(io), + ublk_bpf_get_io_tag(io), + off, sects, res); + if (res < 0) { + ublk_bpf_complete_io(io, res); + return ublk_bpf_return_val(UBLK_BPF_IO_QUEUED, 0); + } + + /* split this io to one 512bytes sub-io and the remainder */ + if (_off < 512 && res > 512) + return ublk_bpf_return_val(UBLK_BPF_IO_CONTINUE, 512); + + /* complete the whole io command after the 2nd sub-io is queued */ + ublk_bpf_complete_io(io, res); + return ublk_bpf_return_val(UBLK_BPF_IO_QUEUED, 0); +} + + static inline ublk_bpf_return_t __ublk_null_handle_io(const struct ublk_bpf_io *io, unsigned int _off) { unsigned long off = -1, sects = -1; @@ -60,4 +94,16 @@ struct ublk_bpf_ops null_ublk_bpf_ops = { .detach_dev = (void *)ublk_null_detach_dev, }; +SEC("struct_ops/ublk_bpf_queue_io_cmd") +ublk_bpf_return_t BPF_PROG(ublk_null_handle_io_split, struct ublk_bpf_io *io, unsigned int off) +{ + return __ublk_null_handle_io_split(io, off); +} + +SEC(".struct_ops.link") +struct ublk_bpf_ops null_ublk_bpf_ops_split = { + .id = 1, + .queue_io_cmd = (void *)ublk_null_handle_io_split, +}; + char LICENSE[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/ublk/test_null_03.sh b/tools/testing/selftests/ublk/test_null_03.sh new file mode 100755 index 000000000000..c0b3a4d941c9 --- /dev/null +++ b/tools/testing/selftests/ublk/test_null_03.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +. test_common.sh + +TID="null_03" +ERR_CODE=0 + +# prepare and register & pin bpf prog +_prep_bpf_test "null" ublk_null.bpf.o + +# add two ublk null disks with the pinned bpf prog +_add_ublk_dev -t null -n 0 --bpf_prog 1 --quiet + +# run fio over the ublk disk +fio --name=job1 --filename=/dev/ublkb0 --ioengine=libaio --rw=readwrite --iodepth=32 --size=256M > /dev/null 2>&1 +ERR_CODE=$? + +# clean and unregister & unpin the bpf prog +_cleanup_bpf_test "null" + +_show_result $TID $ERR_CODE -- 2.47.0