summaryrefslogtreecommitdiff
path: root/cmd/ioworkload/scenario_readwrite.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-09 22:09:13 +0300
committerPaul Buetow <paul@buetow.org>2026-06-09 22:09:13 +0300
commit3cd5e655ee1768b4118815d1ea887acdd57eb498 (patch)
tree05285bc148faff79f931059aff97b8d3fbb9b126 /cmd/ioworkload/scenario_readwrite.go
parent57615945e6796950e7095a3ee8a97651ae3f1bd9 (diff)
test: add coverage for pidfd_send_signal and fadvise64
pidfd_send_signal (FamilyIPC, KindFd@arg0) and fadvise64 (KindFd, UNCLASSIFIED fd-based hint) previously had no end-to-end integration coverage despite correct classification/tracing. pidfd_send_signal: add a pidfd-send-signal ioworkload scenario that opens a pidfd for the current process and issues a sig-0 liveness probe (delivers nothing, safe to target self) via syscall.Syscall6 with the per-arch nr 424. TestPidfdSendSignal asserts enter_pidfd_send_signal is captured; pidfd_send_signal added to the pidfd -trace-syscalls list. fadvise64: add readwrite-fadvise64 and readwrite-fadvise64-ebadf scenarios using unix.Fadvise(fd, 0, 0, FADV_NORMAL), mirroring the readahead tests. TestReadwriteFadvise64 asserts enter_fadvise64 with Bytes==0 (UNCLASSIFIED: offset/len are hints, not bytes transferred) and positive duration; the ebadf variant asserts enter capture with Bytes==0 on the failing call. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'cmd/ioworkload/scenario_readwrite.go')
-rw-r--r--cmd/ioworkload/scenario_readwrite.go44
1 files changed, 44 insertions, 0 deletions
diff --git a/cmd/ioworkload/scenario_readwrite.go b/cmd/ioworkload/scenario_readwrite.go
index 21fba8e..53a366e 100644
--- a/cmd/ioworkload/scenario_readwrite.go
+++ b/cmd/ioworkload/scenario_readwrite.go
@@ -385,6 +385,50 @@ func readwriteReadaheadEbadf() error {
return nil
}
+// readwriteFadvise64 opens a file, writes data, then calls fadvise64(2) on it.
+// fadvise64(fd, offset, len, advice) declares an access-pattern hint for the
+// file's page cache; offset=0/len=0 means "the whole file". It returns 0 on
+// success / -1 on error and transfers NO bytes to userspace, so ior classifies
+// it KindFd / UNCLASSIFIED (offset/len are hint parameters, not bytes moved).
+// The scenario exercises the enter fd_event (fd at args[0]) and the exit
+// ret_event end-to-end. unix.Fadvise wraps the per-arch fadvise64 syscall.
+func readwriteFadvise64() error {
+ dir, cleanup, err := makeTempDir("readwrite-fadvise64")
+ if err != nil {
+ return err
+ }
+ defer cleanup()
+
+ path := filepath.Join(dir, "fadvise64file.txt")
+ fd, err := syscall.Open(path, syscall.O_RDWR|syscall.O_CREAT, 0o644)
+ if err != nil {
+ return fmt.Errorf("open: %w", err)
+ }
+ defer syscall.Close(fd)
+
+ if _, err := syscall.Write(fd, []byte("fadvise64 test data")); err != nil {
+ return fmt.Errorf("write: %w", err)
+ }
+
+ // fadvise64(fd, offset=0, len=0, FADV_NORMAL): hint over the whole file.
+ if err := unix.Fadvise(fd, 0, 0, unix.FADV_NORMAL); err != nil {
+ return fmt.Errorf("fadvise64: %w", err)
+ }
+ return nil
+}
+
+// readwriteFadvise64Ebadf calls fadvise64(2) on an invalid fd.
+// The syscall fails with EBADF, but ior captures the enter_fadvise64 tracepoint
+// because arguments are read on syscall entry before the kernel returns an error.
+func readwriteFadvise64Ebadf() error {
+ for i := 0; i < 5; i++ {
+ if err := unix.Fadvise(99999, 0, 0, unix.FADV_NORMAL); err == nil {
+ return fmt.Errorf("expected EBADF, but fadvise64 succeeded")
+ }
+ }
+ return nil
+}
+
// cachestatRange mirrors the kernel's struct cachestat_range, the second
// cachestat(2) argument: { __u64 off; __u64 len; }. off=0/len=0 means "the
// whole file".