diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-22 22:31:35 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-22 22:31:35 +0200 |
| commit | 4cd2c4e818a1438bf63d1ca05a6cf134f39bc06b (patch) | |
| tree | 40b4ad1ab60a6f50973a66c4e273c91e0d8d265b /integrationtests/cmd | |
| parent | 8e52ba5a8661c717f45e00608ad64f0adc6de3e1 (diff) | |
Add copy_file_range support and tracepoint attach tests
Diffstat (limited to 'integrationtests/cmd')
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenario_copy_file_range.go | 78 | ||||
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenarios.go | 2 |
2 files changed, 80 insertions, 0 deletions
diff --git a/integrationtests/cmd/ioworkload/scenario_copy_file_range.go b/integrationtests/cmd/ioworkload/scenario_copy_file_range.go new file mode 100644 index 0000000..87531b0 --- /dev/null +++ b/integrationtests/cmd/ioworkload/scenario_copy_file_range.go @@ -0,0 +1,78 @@ +package main + +import ( + "fmt" + "path/filepath" + "syscall" +) + +// SYS_COPY_FILE_RANGE on x86_64 Linux. +const sysCopyFileRange = 326 + +// copyFileRangeBasic copies bytes from a source file to a destination file +// using copy_file_range(2) with flags=0 as required by the manpage. +func copyFileRangeBasic() error { + dir, cleanup, err := makeTempDir("copy-file-range-basic") + if err != nil { + return err + } + defer cleanup() + + srcPath := filepath.Join(dir, "copyrangesrc.txt") + dstPath := filepath.Join(dir, "copyrangedst.txt") + + srcFd, err := syscall.Open(srcPath, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open source: %w", err) + } + defer syscall.Close(srcFd) + + dstFd, err := syscall.Open(dstPath, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open destination: %w", err) + } + defer syscall.Close(dstFd) + + data := []byte("copy_file_range integration data") + if _, err := syscall.Write(srcFd, data); err != nil { + return fmt.Errorf("write source: %w", err) + } + + n, _, errno := syscall.Syscall6(uintptr(sysCopyFileRange), uintptr(srcFd), 0, uintptr(dstFd), 0, uintptr(len(data)), 0) + if errno != 0 { + return fmt.Errorf("copy_file_range: %w", errno) + } + if n == 0 { + return fmt.Errorf("copy_file_range copied 0 bytes") + } + + return nil +} + +// copyFileRangeBadDstFd calls copy_file_range(2) with an invalid destination fd. +// The syscall should fail with EBADF, while still emitting the enter tracepoint. +func copyFileRangeBadDstFd() error { + dir, cleanup, err := makeTempDir("copy-file-range-bad-dst") + if err != nil { + return err + } + defer cleanup() + + srcPath := filepath.Join(dir, "copyrangeebadfsrc.txt") + srcFd, err := syscall.Open(srcPath, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open source: %w", err) + } + defer syscall.Close(srcFd) + + if _, err := syscall.Write(srcFd, []byte("copy_file_range ebadf data")); err != nil { + return fmt.Errorf("write source: %w", err) + } + + _, _, errno := syscall.Syscall6(uintptr(sysCopyFileRange), uintptr(srcFd), 0, uintptr(99999), 0, uintptr(16), 0) + if errno != syscall.EBADF { + return fmt.Errorf("expected EBADF from copy_file_range with invalid dst fd, got %v", errno) + } + + return nil +} diff --git a/integrationtests/cmd/ioworkload/scenarios.go b/integrationtests/cmd/ioworkload/scenarios.go index d99b584..f9a8e47 100644 --- a/integrationtests/cmd/ioworkload/scenarios.go +++ b/integrationtests/cmd/ioworkload/scenarios.go @@ -85,6 +85,8 @@ var scenarios = map[string]func() error{ "mmap-basic": mmapBasic, "mmap-msync-sync": mmapMsyncSync, "mmap-msync-invalid-flags": mmapMsyncInvalidFlags, + "copy-file-range-basic": copyFileRangeBasic, + "copy-file-range-bad-dst-fd": copyFileRangeBadDstFd, "truncate-basic": truncateBasic, "truncate-ftruncate": truncateFtruncate, "truncate-enoent": truncateEnoent, |
