}
defer out.Close()
+ // Try fallocate first.
+ for {
+ err = out.fallocate(1 << 10)
+ if err == syscall.EOPNOTSUPP { // The underlying file system may not support fallocate
+ t.Skip("fallocate is not supported")
+ }
+ if err == syscall.EINTR {
+ continue // try again
+ }
+ if err != nil {
+ t.Fatalf("fallocate failed: %v", err)
+ }
+ break
+ }
+
// Mmap 1 MiB initially, and grow to 2 and 3 MiB.
// Check if the file size and disk usage is expected.
for _, sz := range []int64{1 << 20, 2 << 20, 3 << 20} {
if err != nil {
return err
}
- cursize := uint64(stat.Size())
+ // F_PEOFPOSMODE allocates from the end of the file, so we want the size difference.
+ // Apparently, it uses the end of the allocation, instead of the logical end of the
+ // the file.
+ cursize := uint64(stat.Sys().(*syscall.Stat_t).Blocks * 512) // allocated size
if size <= cursize {
return nil
}
Flags: syscall.F_ALLOCATEALL,
Posmode: syscall.F_PEOFPOSMODE,
Offset: 0,
- Length: int64(size - cursize), // F_PEOFPOSMODE allocates from the end of the file, so we want the size difference here
+ Length: int64(size - cursize),
}
_, _, errno := syscall.Syscall(syscall.SYS_FCNTL, uintptr(out.f.Fd()), syscall.F_PREALLOCATE, uintptr(unsafe.Pointer(store)))