diff options
Diffstat (limited to 'integrationtests/cmd')
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenario_mmap.go | 110 | ||||
| -rw-r--r-- | integrationtests/cmd/ioworkload/scenarios.go | 3 |
2 files changed, 113 insertions, 0 deletions
diff --git a/integrationtests/cmd/ioworkload/scenario_mmap.go b/integrationtests/cmd/ioworkload/scenario_mmap.go new file mode 100644 index 0000000..e7b9f02 --- /dev/null +++ b/integrationtests/cmd/ioworkload/scenario_mmap.go @@ -0,0 +1,110 @@ +package main + +import ( + "fmt" + "path/filepath" + "syscall" + "unsafe" +) + +// mmapBasic creates a file-backed shared mapping. +// mmap(2) allows closing the fd after mapping without invalidating the mapping. +func mmapBasic() error { + dir, cleanup, err := makeTempDir("mmap-basic") + if err != nil { + return err + } + defer cleanup() + + path := filepath.Join(dir, "mmapfile.txt") + fd, err := syscall.Open(path, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open: %w", err) + } + defer syscall.Close(fd) + + data := []byte("mmap shared page data") + if _, err := syscall.Write(fd, data); err != nil { + return fmt.Errorf("write: %w", err) + } + + mapped, err := syscall.Mmap(fd, 0, len(data), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return fmt.Errorf("mmap: %w", err) + } + defer syscall.Munmap(mapped) + + copy(mapped[:4], []byte("MMAP")) + return nil +} + +// mmapMsyncSync maps a file and flushes modifications via msync(2). +// Per msync(2), callers should specify exactly one of MS_SYNC or MS_ASYNC. +func mmapMsyncSync() error { + dir, cleanup, err := makeTempDir("mmap-msync-sync") + if err != nil { + return err + } + defer cleanup() + + path := filepath.Join(dir, "msyncfile.txt") + fd, err := syscall.Open(path, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open: %w", err) + } + defer syscall.Close(fd) + + data := []byte("msync shared page data") + if _, err := syscall.Write(fd, data); err != nil { + return fmt.Errorf("write: %w", err) + } + + mapped, err := syscall.Mmap(fd, 0, len(data), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return fmt.Errorf("mmap: %w", err) + } + defer syscall.Munmap(mapped) + + copy(mapped[:5], []byte("MSYNC")) + + _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(&mapped[0])), uintptr(len(mapped)), uintptr(syscall.MS_SYNC)) + if errno != 0 { + return fmt.Errorf("msync: %w", errno) + } + return nil +} + +// mmapMsyncInvalidFlags calls msync(2) with both MS_SYNC and MS_ASYNC. +// The kernel returns EINVAL, but enter_msync should still be captured. +func mmapMsyncInvalidFlags() error { + dir, cleanup, err := makeTempDir("mmap-msync-invalid-flags") + if err != nil { + return err + } + defer cleanup() + + path := filepath.Join(dir, "msyncinvalidfile.txt") + fd, err := syscall.Open(path, syscall.O_RDWR|syscall.O_CREAT|syscall.O_TRUNC, 0o644) + if err != nil { + return fmt.Errorf("open: %w", err) + } + defer syscall.Close(fd) + + data := []byte("msync invalid flags data") + if _, err := syscall.Write(fd, data); err != nil { + return fmt.Errorf("write: %w", err) + } + + mapped, err := syscall.Mmap(fd, 0, len(data), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) + if err != nil { + return fmt.Errorf("mmap: %w", err) + } + defer syscall.Munmap(mapped) + + flags := syscall.MS_SYNC | syscall.MS_ASYNC + _, _, errno := syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(&mapped[0])), uintptr(len(mapped)), uintptr(flags)) + if errno != syscall.EINVAL { + return fmt.Errorf("expected EINVAL from msync with both MS_SYNC|MS_ASYNC, got %v", errno) + } + return nil +} diff --git a/integrationtests/cmd/ioworkload/scenarios.go b/integrationtests/cmd/ioworkload/scenarios.go index 4bd85b6..d99b584 100644 --- a/integrationtests/cmd/ioworkload/scenarios.go +++ b/integrationtests/cmd/ioworkload/scenarios.go @@ -82,6 +82,9 @@ var scenarios = map[string]func() error{ "sync-fsync-ebadf": syncFsyncEbadf, "sync-fdatasync-ebadf": syncFdatasyncEbadf, "sync-file-range-ebadf": syncFileRangeEbadf, + "mmap-basic": mmapBasic, + "mmap-msync-sync": mmapMsyncSync, + "mmap-msync-invalid-flags": mmapMsyncInvalidFlags, "truncate-basic": truncateBasic, "truncate-ftruncate": truncateFtruncate, "truncate-enoent": truncateEnoent, |
