summaryrefslogtreecommitdiff
path: root/cmd/ioworkload/scenario_truncate.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-24 20:36:26 +0300
committerPaul Buetow <paul@buetow.org>2026-04-24 20:36:26 +0300
commit92a36a8c5f23756b8c6d721e89450752409ddd75 (patch)
tree52adee49828831feb0ca557e7df736726faedac3 /cmd/ioworkload/scenario_truncate.go
parentfadbf135d0b251387fd785083df79e27d1025cac (diff)
task a8: move all binaries under ./cmd/<name>/main.go
Relocates the two non-canonical main packages so every binary in the repo lives at ./cmd/<BINARY>/main.go: - tools/filewriter/ -> cmd/filewriter/ - integrationtests/cmd/ioworkload/ (20 files) -> cmd/ioworkload/ Consumers updated: - Magefile.go: workloadSourcePath now ./cmd/ioworkload - integrationtests/README.md: structure note points at ../cmd/ioworkload Files moved with git mv so git log --follow history is preserved. cmd/ior/main.go was already canonical and is untouched. Verified: mage build produces the ior binary; go build ./cmd/... builds filewriter and ioworkload; go test ./cmd/ioworkload passes; go vet ./cmd/filewriter ./cmd/ioworkload is clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'cmd/ioworkload/scenario_truncate.go')
-rw-r--r--cmd/ioworkload/scenario_truncate.go93
1 files changed, 93 insertions, 0 deletions
diff --git a/cmd/ioworkload/scenario_truncate.go b/cmd/ioworkload/scenario_truncate.go
new file mode 100644
index 0000000..04288d5
--- /dev/null
+++ b/cmd/ioworkload/scenario_truncate.go
@@ -0,0 +1,93 @@
+package main
+
+import (
+ "fmt"
+ "path/filepath"
+ "runtime"
+ "syscall"
+ "unsafe"
+)
+
+// truncateBasic opens a file, writes data, then truncates it via
+// syscall.Truncate which uses SYS_TRUNCATE directly on amd64 (path-based).
+func truncateBasic() error {
+ dir, cleanup, err := makeTempDir("truncate-basic")
+ if err != nil {
+ return err
+ }
+ defer cleanup()
+
+ path := filepath.Join(dir, "truncfile.txt")
+ fd, err := syscall.Open(path, syscall.O_RDWR|syscall.O_CREAT, 0o644)
+ if err != nil {
+ return fmt.Errorf("open: %w", err)
+ }
+
+ if _, err := syscall.Write(fd, []byte("truncate this content")); err != nil {
+ syscall.Close(fd)
+ return fmt.Errorf("write: %w", err)
+ }
+ syscall.Close(fd)
+
+ return syscall.Truncate(path, 5)
+}
+
+// truncateFtruncate opens a file, writes data, then truncates it via
+// syscall.Ftruncate which uses SYS_FTRUNCATE directly on amd64 (fd-based).
+func truncateFtruncate() error {
+ dir, cleanup, err := makeTempDir("truncate-ftruncate")
+ if err != nil {
+ return err
+ }
+ defer cleanup()
+
+ path := filepath.Join(dir, "ftruncfile.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("ftruncate this content")); err != nil {
+ return fmt.Errorf("write: %w", err)
+ }
+ return syscall.Ftruncate(fd, 5)
+}
+
+// truncateEnoent attempts to truncate a nonexistent file via raw SYS_TRUNCATE.
+// The syscall fails with ENOENT, but ior captures the enter_truncate
+// tracepoint because the path is read on entry.
+func truncateEnoent() error {
+ dir, cleanup, err := makeTempDir("truncate-enoent")
+ if err != nil {
+ return err
+ }
+ defer cleanup()
+
+ path := filepath.Join(dir, "truncate-enoent-missing.txt")
+ pathBytes, err := syscall.BytePtrFromString(path)
+ if err != nil {
+ return fmt.Errorf("path bytes: %w", err)
+ }
+ // Retry a few times to make this test resilient under high integration
+ // parallelism where a single failed syscall event can be dropped.
+ for i := 0; i < 5; i++ {
+ _, _, errno := syscall.Syscall(syscall.SYS_TRUNCATE, uintptr(unsafe.Pointer(pathBytes)), 0, 0)
+ runtime.KeepAlive(pathBytes)
+ if errno == 0 {
+ return fmt.Errorf("expected ENOENT, but truncate succeeded")
+ }
+ }
+ return nil
+}
+
+// truncateFtruncateEbadf calls raw SYS_FTRUNCATE on an invalid fd (99999).
+// The syscall fails with EBADF, but ior captures the enter_ftruncate
+// tracepoint because it is recorded on syscall entry.
+func truncateFtruncateEbadf() error {
+ _, _, errno := syscall.Syscall(syscall.SYS_FTRUNCATE, 99999, 0, 0)
+ if errno == 0 {
+ return fmt.Errorf("expected EBADF, but ftruncate succeeded")
+ }
+ return nil
+}