diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-21 19:42:40 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-21 19:42:40 +0200 |
| commit | 5234ae813b60b823bc984ca8862f078ed4fe71a6 (patch) | |
| tree | 6264c667c31c443fe7ecb59b3346fbd713bf2523 /integrationtests | |
| parent | 4253a94b9bcb03c3c59e37a05ac006e79dfdc8bf (diff) | |
Add io_uring integration tests and workload scenarios
Implement iouring_test.go with tests for io_uring_setup, io_uring_enter,
and io_uring_register tracepoints. Add corresponding workload scenarios
using raw syscalls (425, 426, 427) since Go stdlib doesn't wrap io_uring
on amd64.
- iouring-setup: creates io_uring instance via io_uring_setup(2)
- iouring-enter: creates ring, calls io_uring_enter(2) with zero ops
- iouring-register: creates ring, calls io_uring_register(2) with PROBE
Task #343
Amp-Thread-ID: https://ampcode.com/threads/T-019c8149-2aa6-75fb-88f3-dd6bd3a2b654
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'integrationtests')
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenarios.go | 89 | ||||
| -rw-r--r-- | integrationtests/iouring_test.go | 33 |
2 files changed, 122 insertions, 0 deletions
diff --git a/integrationtests/cmd/ioworkload/scenarios.go b/integrationtests/cmd/ioworkload/scenarios.go index c4583e9..06e202d 100644 --- a/integrationtests/cmd/ioworkload/scenarios.go +++ b/integrationtests/cmd/ioworkload/scenarios.go @@ -54,6 +54,9 @@ var scenarios = map[string]func() error{ "sync-sync-file-range": syncSyncFileRange, "truncate-basic": truncateBasic, "truncate-ftruncate": truncateFtruncate, + "iouring-setup": iouringSetup, + "iouring-enter": iouringEnter, + "iouring-register": iouringRegister, } func makeTempDir(prefix string) (string, func(), error) { @@ -1487,3 +1490,89 @@ func openByHandleAtSyscall(mountFD int, handle []byte, flags int) (int, error) { } return int(fd), nil } + +const ( + sysIoUringSetup = 425 + sysIoUringEnter = 426 + sysIoUringRegister = 427 + + // io_uring_params struct size: 10 x uint32 + io_sqring_offsets(40) + io_cqring_offsets(40) = 120 bytes. + ioUringParamsSize = 120 + + ioringRegisterProbe = 8 // IORING_REGISTER_PROBE +) + +// iouringSetup creates an io_uring instance via io_uring_setup(2) and closes the fd. +func iouringSetup() error { + fd, err := ioUringSetupRing(1) + if err != nil { + return err + } + return syscall.Close(fd) +} + +// iouringEnter creates an io_uring instance, then calls io_uring_enter(2) +// with zero submissions/completions to exercise the enter tracepoint. +func iouringEnter() error { + fd, err := ioUringSetupRing(1) + if err != nil { + return err + } + defer syscall.Close(fd) + + _, _, errno := syscall.Syscall6( + sysIoUringEnter, + uintptr(fd), + 0, // to_submit + 0, // min_complete + 0, // flags + 0, // sig + 0, // sz + ) + if errno != 0 { + return fmt.Errorf("io_uring_enter: %w", errno) + } + return nil +} + +// iouringRegister creates an io_uring instance, then calls io_uring_register(2) +// with IORING_REGISTER_PROBE to exercise the register tracepoint. +func iouringRegister() error { + fd, err := ioUringSetupRing(1) + if err != nil { + return err + } + defer syscall.Close(fd) + + // io_uring_probe header is 16 bytes; we don't need probe_op entries. + var probeBuf [16]byte + _, _, errno := syscall.Syscall6( + sysIoUringRegister, + uintptr(fd), + ioringRegisterProbe, + uintptr(unsafe.Pointer(&probeBuf[0])), + 0, // nr_args (0 ops requested) + 0, 0, + ) + runtime.KeepAlive(probeBuf) + if errno != 0 { + return fmt.Errorf("io_uring_register: %w", errno) + } + return nil +} + +// ioUringSetupRing calls io_uring_setup(2) and returns the ring fd. +func ioUringSetupRing(entries uint32) (int, error) { + var params [ioUringParamsSize]byte + fd, _, errno := syscall.Syscall( + sysIoUringSetup, + uintptr(entries), + uintptr(unsafe.Pointer(¶ms[0])), + 0, + ) + runtime.KeepAlive(params) + if errno != 0 { + return 0, fmt.Errorf("io_uring_setup: %w", errno) + } + return int(fd), nil +} diff --git a/integrationtests/iouring_test.go b/integrationtests/iouring_test.go new file mode 100644 index 0000000..20c156c --- /dev/null +++ b/integrationtests/iouring_test.go @@ -0,0 +1,33 @@ +package integrationtests + +import "testing" + +func TestIouringSetup(t *testing.T) { + runScenario(t, "iouring-setup", []ExpectedEvent{ + { + Tracepoint: "enter_io_uring_setup", + Comm: "ioworkload", + MinCount: 1, + }, + }) +} + +func TestIouringEnter(t *testing.T) { + runScenario(t, "iouring-enter", []ExpectedEvent{ + { + Tracepoint: "enter_io_uring_enter", + Comm: "ioworkload", + MinCount: 1, + }, + }) +} + +func TestIouringRegister(t *testing.T) { + runScenario(t, "iouring-register", []ExpectedEvent{ + { + Tracepoint: "enter_io_uring_register", + Comm: "ioworkload", + MinCount: 1, + }, + }) +} |
