This snippet is primarily meant as a building block for tools used to validate system IO, in particular for testing how system behaves with regard to IO error handling.
package main
// A dummy program designed for validating correct EIO reporting from the
// kernel on BrickstorOS.
//
// Build and run something like this, where name of program is doio:
// # ./doio /dev/rdsk/c0t5000C5004271FCCFd0s0
//
// The only valid argument is path to a file, which could be a raw disk
// device or any old file.
import (
"fmt"
"os"
"syscall"
)
const (
openMode = 0644
openFlags = syscall.O_RDONLY | syscall.O_NDELAY
loopLimit = 1e5
)
func main() {
var fd, loopcnt, bytecnt int
var path string
buf := make([]byte, 4096)
if len(os.Args) < 2 {
os.Exit(1)
} else {
path = os.Args[1]
}
if info, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
fmt.Printf("%v\n", err)
os.Exit(1)
}
} else {
fd, err = syscall.Open(path, openFlags, openMode)
if err != nil {
fmt.Printf("%v, failed to open %s\n", err, path)
os.Exit(1)
}
fmt.Printf("Opened '%s' for reading\n", info.Name())
for loopcnt < loopLimit {
n, err := syscall.Read(fd, buf)
if err != nil {
// EIO is what we are interested to trap
if err == syscall.EIO {
fmt.Printf("Received EIO (0x5)\n")
os.Exit(5)
// Some other unexpected condition
} else {
fmt.Printf("%v\n", err)
os.Exit(1)
}
} else {
if loopcnt%1000 == 0 {
fmt.Printf("loopcnt: %-8d | bytecnt: %d\n",
loopcnt, bytecnt)
}
loopcnt++
bytecnt += n
}
}
}
os.Exit(0)
}