-
-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Direct IO library factored from github.com/ncw/stressdisk
- Loading branch information
0 parents
commit f5011e2
Showing
8 changed files
with
294 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*~ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
Copyright (C) 2012 by Nick Craig-Wood http://www.craig-wood.com/nick/ | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
DirectIO | ||
======== | ||
|
||
This is library for the Go language to enable use of Direct IO under | ||
all supported OSes of Go. | ||
|
||
Direct IO does IO to and from disk without buffering data in the OS. | ||
It is useful when you are reading or writing lots of data you don't | ||
want to fill the OS cache up with. | ||
|
||
Install | ||
------- | ||
|
||
Directio is a Go library and installs in the usual way | ||
|
||
go get github.com/ncw/directio | ||
|
||
Usage | ||
----- | ||
|
||
Instead of using os.OpenFile use directio.OpenFile | ||
|
||
in, err := directio.OpenFile(file, os.O_RDONLY, 0666) | ||
|
||
And when reading or writing blocks, make sure you do them in chunks of | ||
directio.BlockSize using memory allocated by directio.AlignedBlock | ||
|
||
block := directio.AlignedBlock(BlockSize) | ||
_, err := io.ReadFull(in, block) | ||
|
||
License | ||
------- | ||
|
||
This is free software under the terms of MIT the license (check the | ||
COPYING file included in this package). | ||
|
||
Contact and support | ||
------------------- | ||
|
||
The project website is at: | ||
|
||
- https://github.com/ncw/directio | ||
|
||
There you can file bug reports, ask for help or contribute patches. | ||
|
||
Authors | ||
------- | ||
|
||
- Nick Craig-Wood <[email protected]> | ||
|
||
Contributors | ||
------------ | ||
|
||
- Your name goes here! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// This is library for the Go language to enable use of Direct IO under | ||
// all supported OSes of Go. | ||
// | ||
// Direct IO does IO to and from disk without buffering data in the OS. | ||
// It is useful when you are reading or writing lots of data you don't | ||
// want to fill the OS cache up with. | ||
// | ||
// Instead of using os.OpenFile use directio.OpenFile | ||
// | ||
// in, err := directio.OpenFile(file, os.O_RDONLY, 0666) | ||
// | ||
// And when reading or writing blocks, make sure you do them in chunks of | ||
// directio.BlockSize using memory allocated by directio.AlignedBlock | ||
// | ||
// block := directio.AlignedBlock(BlockSize) | ||
// _, err := io.ReadFull(in, block) | ||
package directio | ||
|
||
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)) | ||
} | ||
|
||
// AlignedBlock returns []byte of size BlockSize aligned to a multiple | ||
// of AlignSize in memory (must be power of two) | ||
func AlignedBlock(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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Direct IO for darwin | ||
|
||
package directio | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"syscall" | ||
) | ||
|
||
const ( | ||
// OSX doesn't need any alignment | ||
AlignSize = 0 | ||
|
||
// Minimum block size | ||
BlockSize = 4096 | ||
) | ||
|
||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Direct IO for freebsd | ||
|
||
package directio | ||
|
||
import ( | ||
"os" | ||
"syscall" | ||
) | ||
|
||
const ( | ||
// Size to align the buffer to | ||
AlignSize = 4096 | ||
|
||
// Minimum block size | ||
BlockSize = 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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// Direct IO for linux | ||
|
||
package directio | ||
|
||
import ( | ||
"os" | ||
"syscall" | ||
) | ||
|
||
const ( | ||
// Size to align the buffer to | ||
AlignSize = 4096 | ||
|
||
// Minimum block size | ||
BlockSize = 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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Direct IO for windows | ||
|
||
package directio | ||
|
||
import ( | ||
"os" | ||
"syscall" | ||
"unicode/utf16" | ||
) | ||
|
||
const ( | ||
// Size to align the buffer to | ||
AlignSize = 4096 | ||
|
||
// Minimum block size | ||
BlockSize = 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 | ||
} |