diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-21 22:03:57 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-21 22:03:57 +0200 |
| commit | 3ec3c117bb280a377fea1a3eef84a70e2a3d4150 (patch) | |
| tree | b017e330eeaa1cafe95d2a730675b46342afd92a /integrationtests/cmd/ioworkload/scenario_iouring.go | |
| parent | 311b827599251d8d68526293815e8d4dcba632c8 (diff) | |
Split ioworkload scenarios.go into per-category files
Split the 2494-line scenarios.go monolith into 14 focused files by
syscall category: open, readwrite, close, dup, fcntl, rename, link,
unlink, dir, stat, sync, truncate, iouring, plus the slimmed-down
scenarios.go containing only the registry map, makeTempDir, and crash.
Extracted rawLink, rawSymlink, rawReadlink helpers in scenario_link.go
to reduce code duplication in linkBasic.
Task: #349 (Go best practices: split oversized scenarios file)
Amp-Thread-ID: https://ampcode.com/threads/T-019c81c6-e1b6-747a-9144-40f6be997e60
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'integrationtests/cmd/ioworkload/scenario_iouring.go')
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenario_iouring.go | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/integrationtests/cmd/ioworkload/scenario_iouring.go b/integrationtests/cmd/ioworkload/scenario_iouring.go new file mode 100644 index 0000000..b1aac4e --- /dev/null +++ b/integrationtests/cmd/ioworkload/scenario_iouring.go @@ -0,0 +1,129 @@ +package main + +import ( + "fmt" + "runtime" + "syscall" + "unsafe" +) + +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 +} + +// iouringEnterEbadf calls io_uring_enter on an invalid fd. +// The syscall fails with EBADF, but ior captures the enter_io_uring_enter tracepoint. +func iouringEnterEbadf() error { + _, _, errno := syscall.Syscall6( + sysIoUringEnter, + 99999, // invalid fd + 0, // to_submit + 0, // min_complete + 0, // flags + 0, // sig + 0, // sz + ) + if errno == 0 { + return fmt.Errorf("expected EBADF, but io_uring_enter succeeded") + } + return nil +} + +// iouringRegisterEbadf calls io_uring_register on an invalid fd. +// The syscall fails with EBADF, but ior captures the enter_io_uring_register tracepoint. +func iouringRegisterEbadf() error { + _, _, errno := syscall.Syscall6( + sysIoUringRegister, + 99999, // invalid fd + ioringRegisterProbe, + 0, // arg (NULL) + 0, // nr_args + 0, 0, + ) + if errno == 0 { + return fmt.Errorf("expected EBADF, but io_uring_register succeeded") + } + 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 +} |
