mirror of
https://github.com/minio/minio.git
synced 2025-11-09 05:34:56 -05:00
fix: add support for O_DIRECT reads for erasure backends (#10718)
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/minio/minio/cmd/config/storageclass"
|
||||
"github.com/minio/minio/pkg/disk"
|
||||
)
|
||||
|
||||
@@ -1063,62 +1064,71 @@ func TestXLStorageReadFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Following block validates all ReadFile test cases.
|
||||
for i, testCase := range testCases {
|
||||
var n int64
|
||||
// Common read buffer.
|
||||
var buf = make([]byte, testCase.bufSize)
|
||||
n, err = xlStorage.ReadFile(context.Background(), testCase.volume, testCase.fileName, testCase.offset, buf, v)
|
||||
if err != nil && testCase.expectedErr != nil {
|
||||
// Validate if the type string of the errors are an exact match.
|
||||
if err.Error() != testCase.expectedErr.Error() {
|
||||
if runtime.GOOS != globalWindowsOSName {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got: %s", i+1, testCase, testCase.expectedErr, err)
|
||||
} else {
|
||||
var resultErrno, expectErrno uintptr
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
if errno, pok := pathErr.Err.(syscall.Errno); pok {
|
||||
resultErrno = uintptr(errno)
|
||||
}
|
||||
}
|
||||
if pathErr, ok := testCase.expectedErr.(*os.PathError); ok {
|
||||
if errno, pok := pathErr.Err.(syscall.Errno); pok {
|
||||
expectErrno = uintptr(errno)
|
||||
}
|
||||
}
|
||||
if !(expectErrno != 0 && resultErrno != 0 && expectErrno == resultErrno) {
|
||||
for l := 0; l < 2; l++ {
|
||||
// 1st loop tests with dma=write, 2nd loop tests with dma=read-write.
|
||||
if l == 1 {
|
||||
globalStorageClass.DMA.DMA = storageclass.DMAReadWrite
|
||||
}
|
||||
// Following block validates all ReadFile test cases.
|
||||
for i, testCase := range testCases {
|
||||
var n int64
|
||||
// Common read buffer.
|
||||
var buf = make([]byte, testCase.bufSize)
|
||||
n, err = xlStorage.ReadFile(context.Background(), testCase.volume, testCase.fileName, testCase.offset, buf, v)
|
||||
if err != nil && testCase.expectedErr != nil {
|
||||
// Validate if the type string of the errors are an exact match.
|
||||
if err.Error() != testCase.expectedErr.Error() {
|
||||
if runtime.GOOS != globalWindowsOSName {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got: %s", i+1, testCase, testCase.expectedErr, err)
|
||||
} else {
|
||||
var resultErrno, expectErrno uintptr
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
if errno, pok := pathErr.Err.(syscall.Errno); pok {
|
||||
resultErrno = uintptr(errno)
|
||||
}
|
||||
}
|
||||
if pathErr, ok := testCase.expectedErr.(*os.PathError); ok {
|
||||
if errno, pok := pathErr.Err.(syscall.Errno); pok {
|
||||
expectErrno = uintptr(errno)
|
||||
}
|
||||
}
|
||||
if !(expectErrno != 0 && resultErrno != 0 && expectErrno == resultErrno) {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got: %s", i+1, testCase, testCase.expectedErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Err unexpected EOF special case, where we verify we have provided a larger
|
||||
// buffer than the data itself, but the results are in-fact valid. So we validate
|
||||
// this error condition specifically treating it as a good condition with valid
|
||||
// results. In this scenario return 'n' is always lesser than the input buffer.
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
if !bytes.Equal(testCase.expectedBuf, buf[:n]) {
|
||||
t.Errorf("Case: %d %#v, expected: \"%s\", got: \"%s\"", i+1, testCase, string(testCase.expectedBuf), string(buf[:n]))
|
||||
}
|
||||
if n > int64(len(buf)) {
|
||||
t.Errorf("Case: %d %#v, expected: %d, got: %d", i+1, testCase, testCase.bufSize, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Err unexpected EOF special case, where we verify we have provided a larger
|
||||
// buffer than the data itself, but the results are in-fact valid. So we validate
|
||||
// this error condition specifically treating it as a good condition with valid
|
||||
// results. In this scenario return 'n' is always lesser than the input buffer.
|
||||
if err == io.ErrUnexpectedEOF {
|
||||
if !bytes.Equal(testCase.expectedBuf, buf[:n]) {
|
||||
t.Errorf("Case: %d %#v, expected: \"%s\", got: \"%s\"", i+1, testCase, string(testCase.expectedBuf), string(buf[:n]))
|
||||
// ReadFile has returned success, but our expected error is non 'nil'.
|
||||
if err == nil && err != testCase.expectedErr {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got :%s", i+1, testCase, testCase.expectedErr, err)
|
||||
}
|
||||
// Expected error retured, proceed further to validate the returned results.
|
||||
if err == nil && err == testCase.expectedErr {
|
||||
if !bytes.Equal(testCase.expectedBuf, buf) {
|
||||
t.Errorf("Case: %d %#v, expected: \"%s\", got: \"%s\"", i+1, testCase, string(testCase.expectedBuf), string(buf[:testCase.bufSize]))
|
||||
}
|
||||
if n > int64(len(buf)) {
|
||||
if n != int64(testCase.bufSize) {
|
||||
t.Errorf("Case: %d %#v, expected: %d, got: %d", i+1, testCase, testCase.bufSize, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
// ReadFile has returned success, but our expected error is non 'nil'.
|
||||
if err == nil && err != testCase.expectedErr {
|
||||
t.Errorf("Case: %d %#v, expected: %s, got :%s", i+1, testCase, testCase.expectedErr, err)
|
||||
}
|
||||
// Expected error retured, proceed further to validate the returned results.
|
||||
if err == nil && err == testCase.expectedErr {
|
||||
if !bytes.Equal(testCase.expectedBuf, buf) {
|
||||
t.Errorf("Case: %d %#v, expected: \"%s\", got: \"%s\"", i+1, testCase, string(testCase.expectedBuf), string(buf[:testCase.bufSize]))
|
||||
}
|
||||
if n != int64(testCase.bufSize) {
|
||||
t.Errorf("Case: %d %#v, expected: %d, got: %d", i+1, testCase, testCase.bufSize, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the flag.
|
||||
globalStorageClass.DMA.DMA = storageclass.DMAWrite
|
||||
|
||||
// TestXLStorage for permission denied.
|
||||
if runtime.GOOS != globalWindowsOSName {
|
||||
permDeniedDir := createPermDeniedFile(t)
|
||||
|
||||
Reference in New Issue
Block a user