//go:build linux package host import ( "os" "path/filepath" "syscall" "time" "unsafe" "github.com/carlosframework/platform/internal/moves" ) // measureDiskSize is how much T11's disk measurement writes and reads back. const measureDiskSize = 64 << 20 // measureDiskRate times writing and reading measureDiskSize under dir with // O_DIRECT, so the page cache neither absorbs the write nor answers the // read (F12). A filesystem that refuses O_DIRECT (tmpfs) is measured with a // plain write, fsync and read instead. func measureDiskRate(dir string, now func() time.Time) (moves.MeasuredRate, error) { path := filepath.Join(dir, "disk") f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_RDWR|syscall.O_DIRECT, 0o600) if err != nil { return measureDiskSynced(dir, now) } defer f.Close() buf := alignedBlock(1 << 20) start := now() for n := 0; n < measureDiskSize; n += len(buf) { if _, err := f.Write(buf); err != nil { return moves.MeasuredRate{}, err } } if err := f.Sync(); err != nil { return moves.MeasuredRate{}, err } if _, err := f.Seek(0, 0); err != nil { return moves.MeasuredRate{}, err } for n := 0; n < measureDiskSize; n += len(buf) { if _, err := f.Read(buf); err != nil { return moves.MeasuredRate{}, err } } return moves.RateOf(2*measureDiskSize, now().Sub(start), now().UTC()), nil } // alignedBlock is a size-byte buffer aligned to 4096 bytes, as O_DIRECT // requires. func alignedBlock(size int) []byte { const align = 4096 b := make([]byte, size+align) off := 0 if r := int(uintptr(unsafe.Pointer(&b[0])) & (align - 1)); r != 0 { off = align - r } return b[off : off+size] }