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_truncate.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_truncate.go')
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenario_truncate.go | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/integrationtests/cmd/ioworkload/scenario_truncate.go b/integrationtests/cmd/ioworkload/scenario_truncate.go new file mode 100644 index 0000000..28be152 --- /dev/null +++ b/integrationtests/cmd/ioworkload/scenario_truncate.go @@ -0,0 +1,89 @@ +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) + } + _, _, 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 +} |
