From 844be1055d78b95ad7f8a26e7cc10ac241d6f849 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Fri, 28 Jun 2013 17:16:06 +0100 Subject: [PATCH] Factor direct io to github.com/ncw/directio --- align.go | 33 ---------------- direct_io_darwin.go | 33 ---------------- direct_io_freebsd.go | 18 --------- direct_io_linux.go | 18 --------- direct_io_windows.go | 89 -------------------------------------------- stressdisk.go | 15 ++++---- 6 files changed, 8 insertions(+), 198 deletions(-) delete mode 100644 align.go delete mode 100644 direct_io_darwin.go delete mode 100644 direct_io_freebsd.go delete mode 100644 direct_io_linux.go delete mode 100644 direct_io_windows.go diff --git a/align.go b/align.go deleted file mode 100644 index 2c4c7af..0000000 --- a/align.go +++ /dev/null @@ -1,33 +0,0 @@ -// Alignment blocks of memory -package main - -import ( - "log" - "unsafe" -) - -// alignment returns alignment of the block in memory -// with reference to AlignSize -func alignment(block []byte, AlignSize int) int { - return int(uintptr(unsafe.Pointer(&block[0])) & uintptr(AlignSize-1)) -} - -// makeAlignedBlock returns []byte of size BlockSize aligned to a -// multiple of AlignSize in memory (must be power of two) -func makeAlignedBlock(BlockSize int) []byte { - block := make([]byte, BlockSize+AlignSize) - if AlignSize == 0 { - return block - } - a := alignment(block, AlignSize) - offset := 0 - if a != 0 { - offset = AlignSize - a - } - block = block[offset : offset+BlockSize] - a = alignment(block, AlignSize) - if a != 0 { - log.Fatal("Failed to align block") - } - return block -} diff --git a/direct_io_darwin.go b/direct_io_darwin.go deleted file mode 100644 index 729ee03..0000000 --- a/direct_io_darwin.go +++ /dev/null @@ -1,33 +0,0 @@ -// Direct IO for darwin - -package main - -import ( - "fmt" - "os" - "syscall" -) - -const ( - // OSX doesn't need any alignment - AlignSize = 0 -) - -func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) { - file, err = os.OpenFile(name, flag, perm) - if err != nil { - return - } - - // Set F_NOCACHE to avoid caching - // F_NOCACHE Turns data caching off/on. A non-zero value in arg turns data caching off. A value - // of zero in arg turns data caching on. - _, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(file.Fd()), syscall.F_NOCACHE, 1) - if e1 != 0 { - err = fmt.Errorf("Failed to set F_NOCACHE: %s", e1) - file.Close() - file = nil - } - - return -} diff --git a/direct_io_freebsd.go b/direct_io_freebsd.go deleted file mode 100644 index 1e1a3a0..0000000 --- a/direct_io_freebsd.go +++ /dev/null @@ -1,18 +0,0 @@ -// Direct IO for freebsd - -package main - -import ( - "os" - "syscall" -) - -const ( - // Size to align the buffer to - AlignSize = 4096 -) - -// OpenFile is a modified version of os.OpenFile which sets O_DIRECT -func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) { - return os.OpenFile(name, syscall.O_DIRECT|flag, perm) -} diff --git a/direct_io_linux.go b/direct_io_linux.go deleted file mode 100644 index c438267..0000000 --- a/direct_io_linux.go +++ /dev/null @@ -1,18 +0,0 @@ -// Direct IO for linux - -package main - -import ( - "os" - "syscall" -) - -const ( - // Size to align the buffer to - AlignSize = 4096 -) - -// OpenFile is a modified version of os.OpenFile which sets O_DIRECT -func OpenFile(name string, flag int, perm os.FileMode) (file *os.File, err error) { - return os.OpenFile(name, syscall.O_DIRECT|flag, perm) -} diff --git a/direct_io_windows.go b/direct_io_windows.go deleted file mode 100644 index e4c942e..0000000 --- a/direct_io_windows.go +++ /dev/null @@ -1,89 +0,0 @@ -// Direct IO for windows - -package main - -import ( - "os" - "syscall" - "unicode/utf16" -) - -const ( - // Size to align the buffer to - AlignSize = 4096 - - // Extra flags for windows - FILE_FLAG_NO_BUFFERING = 0x20000000 - FILE_FLAG_WRITE_THROUGH = 0x80000000 -) - -// utf16FromString returns the UTF-16 encoding of the UTF-8 string -// s, with a terminating NUL added. If s contains a NUL byte at any -// location, it returns (nil, EINVAL). -// -// FIXME copied from go source -func utf16FromString(s string) ([]uint16, error) { - for i := 0; i < len(s); i++ { - if s[i] == 0 { - return nil, syscall.EINVAL - } - } - return utf16.Encode([]rune(s + "\x00")), nil -} - -// OpenFile is a modified version of os.OpenFile which sets the -// passes the following flags to windows CreateFile. -// -// The FILE_FLAG_NO_BUFFERING takes this concept one step further and -// eliminates all read-ahead file buffering and disk caching as well, -// so that all reads are guaranteed to come from the file and not from -// any system buffer or disk cache. When using FILE_FLAG_NO_BUFFERING, -// disk reads and writes must be done on sector boundaries, and buffer -// addresses must be aligned on disk sector boundaries in memory. -// -// FIXME copied from go source then modified -func OpenFile(path string, mode int, perm os.FileMode) (file *os.File, err error) { - if len(path) == 0 { - return nil, &os.PathError{"open", path, syscall.ERROR_FILE_NOT_FOUND} - } - pathp, err := utf16FromString(path) - if err != nil { - return nil, &os.PathError{"open", path, err} - } - var access uint32 - switch mode & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR) { - case os.O_RDONLY: - access = syscall.GENERIC_READ - case os.O_WRONLY: - access = syscall.GENERIC_WRITE - case os.O_RDWR: - access = syscall.GENERIC_READ | syscall.GENERIC_WRITE - } - if mode&syscall.O_CREAT != 0 { - access |= syscall.GENERIC_WRITE - } - if mode&os.O_APPEND != 0 { - access &^= syscall.GENERIC_WRITE - access |= syscall.FILE_APPEND_DATA - } - sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE) - var sa *syscall.SecurityAttributes - var createmode uint32 - switch { - case mode&(syscall.O_CREAT|os.O_EXCL) == (syscall.O_CREAT | os.O_EXCL): - createmode = syscall.CREATE_NEW - case mode&(syscall.O_CREAT|os.O_TRUNC) == (syscall.O_CREAT | os.O_TRUNC): - createmode = syscall.CREATE_ALWAYS - case mode&syscall.O_CREAT == syscall.O_CREAT: - createmode = syscall.OPEN_ALWAYS - case mode&os.O_TRUNC == os.O_TRUNC: - createmode = syscall.TRUNCATE_EXISTING - default: - createmode = syscall.OPEN_EXISTING - } - h, e := syscall.CreateFile(&pathp[0], access, sharemode, sa, createmode, syscall.FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH, 0) - if e != nil { - return nil, &os.PathError{"open", path, e} - } - return os.NewFile(uintptr(h), path), nil -} diff --git a/stressdisk.go b/stressdisk.go index df394b5..3396650 100644 --- a/stressdisk.go +++ b/stressdisk.go @@ -23,6 +23,7 @@ import ( "bytes" "flag" "fmt" + "github.com/ncw/directio" "io" "io/ioutil" "log" @@ -259,9 +260,9 @@ func NewBlockReader(in io.Reader, file string) *BlockReader { func (br *BlockReader) background() { defer br.wg.Done() defer close(br.out) - block1 := makeAlignedBlock(BlockSize) - block2 := makeAlignedBlock(BlockSize) - block3 := makeAlignedBlock(BlockSize) + block1 := directio.AlignedBlock(BlockSize) + block2 := directio.AlignedBlock(BlockSize) + block3 := directio.AlignedBlock(BlockSize) for { _, err := io.ReadFull(br.in, block1) if err != nil { @@ -301,7 +302,7 @@ func (br *BlockReader) Close() { // ReadFile reads the file given and checks it against the random source func ReadFile(file string) { - in, err := OpenFile(file, os.O_RDONLY, 0666) + in, err := directio.OpenFile(file, os.O_RDONLY, 0666) if err != nil { log.Fatalf("Failed to open %s for reading: %s\n", file, err) } @@ -334,7 +335,7 @@ func ReadFile(file string) { // // Returns a true if the write failed, false otherwise. func WriteFile(file string, size int64) bool { - out, err := OpenFile(file, os.O_CREATE|os.O_WRONLY, 0666) + out, err := directio.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0666) if err != nil { log.Fatalf("Couldn't open file %q for write: %s\n", file, err) } @@ -371,13 +372,13 @@ func WriteFile(file string, size int64) bool { // // It reads the files in BlockSize chunks. func ReadTwoFiles(file1, file2 string) { - in1, err := OpenFile(file1, os.O_RDONLY, 0666) + in1, err := directio.OpenFile(file1, os.O_RDONLY, 0666) if err != nil { log.Fatalf("Couldn't open file %q for read\n", file1) } defer in1.Close() - in2, err := OpenFile(file2, os.O_RDONLY, 0666) + in2, err := directio.OpenFile(file2, os.O_RDONLY, 0666) if err != nil { log.Fatalf("Couldn't open file %q for read\n", file2) }