summaryrefslogtreecommitdiff
path: root/integrationtests
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-21 19:42:40 +0200
committerPaul Buetow <paul@buetow.org>2026-02-21 19:42:40 +0200
commit5234ae813b60b823bc984ca8862f078ed4fe71a6 (patch)
tree6264c667c31c443fe7ecb59b3346fbd713bf2523 /integrationtests
parent4253a94b9bcb03c3c59e37a05ac006e79dfdc8bf (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.go89
-rw-r--r--integrationtests/iouring_test.go33
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(&params[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,
+ },
+ })
+}