mirror of
https://github.com/minio/minio.git
synced 2025-11-10 22:10:12 -05:00
use Access() instead of Lstat() for frequent use (#11911)
using Lstat() is causing tiny memory allocations, that are usually wasted and never used, instead we can simply uses Access() call that does 0 memory allocations.
This commit is contained in:
@@ -39,6 +39,7 @@ const (
|
||||
osMetricLstat
|
||||
osMetricRemove
|
||||
osMetricStat
|
||||
osMetricAccess
|
||||
// .... add more
|
||||
|
||||
osMetricLast
|
||||
@@ -94,6 +95,14 @@ func OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) {
|
||||
return os.OpenFile(name, flag, perm)
|
||||
}
|
||||
|
||||
// Access captures time taken to call syscall.Access()
|
||||
// on windows, plan9 and solaris syscall.Access uses
|
||||
// os.Lstat()
|
||||
func Access(name string) error {
|
||||
defer updateOSMetrics(osMetricAccess, name)()
|
||||
return access(name)
|
||||
}
|
||||
|
||||
// Open captures time taken to call os.Open
|
||||
func Open(name string) (*os.File, error) {
|
||||
defer updateOSMetrics(osMetricOpen, name)()
|
||||
|
||||
@@ -24,6 +24,11 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func access(name string) error {
|
||||
_, err := os.Lstat(name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Return all the entries at the directory dirPath.
|
||||
func readDir(dirPath string) (entries []string, err error) {
|
||||
return readDirN(dirPath, -1)
|
||||
|
||||
@@ -25,8 +25,17 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func access(name string) error {
|
||||
if err := unix.Access(name, unix.R_OK|unix.W_OK); err != nil {
|
||||
return &os.PathError{Op: "lstat", Path: name, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The buffer must be at least a block long.
|
||||
// refer https://github.com/golang/go/issues/24015
|
||||
const blockSize = 8 << 10 // 8192
|
||||
|
||||
@@ -24,6 +24,11 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func access(name string) error {
|
||||
_, err := os.Lstat(name)
|
||||
return err
|
||||
}
|
||||
|
||||
// Return all the entries at the directory dirPath.
|
||||
func readDir(dirPath string) (entries []string, err error) {
|
||||
return readDirN(dirPath, -1)
|
||||
|
||||
@@ -17,12 +17,13 @@ func _() {
|
||||
_ = x[osMetricLstat-6]
|
||||
_ = x[osMetricRemove-7]
|
||||
_ = x[osMetricStat-8]
|
||||
_ = x[osMetricLast-9]
|
||||
_ = x[osMetricAccess-9]
|
||||
_ = x[osMetricLast-10]
|
||||
}
|
||||
|
||||
const _osMetric_name = "RemoveAllMkdirAllRenameOpenFileOpenOpenFileDirectIOLstatRemoveStatLast"
|
||||
const _osMetric_name = "RemoveAllMkdirAllRenameOpenFileOpenOpenFileDirectIOLstatRemoveStatAccessLast"
|
||||
|
||||
var _osMetric_index = [...]uint8{0, 9, 17, 23, 31, 35, 51, 56, 62, 66, 70}
|
||||
var _osMetric_index = [...]uint8{0, 9, 17, 23, 31, 35, 51, 56, 62, 66, 72, 76}
|
||||
|
||||
func (i osMetric) String() string {
|
||||
if i >= osMetric(len(_osMetric_index)-1) {
|
||||
|
||||
@@ -529,8 +529,7 @@ func (s *xlStorage) GetDiskID() (string, error) {
|
||||
if err != nil {
|
||||
// If the disk is still not initialized.
|
||||
if osIsNotExist(err) {
|
||||
_, err = Lstat(s.diskPath)
|
||||
if err == nil {
|
||||
if err = Access(s.diskPath); err == nil {
|
||||
// Disk is present but missing `format.json`
|
||||
return "", errUnformattedDisk
|
||||
}
|
||||
@@ -560,8 +559,7 @@ func (s *xlStorage) GetDiskID() (string, error) {
|
||||
if err != nil {
|
||||
// If the disk is still not initialized.
|
||||
if osIsNotExist(err) {
|
||||
_, err = Lstat(s.diskPath)
|
||||
if err == nil {
|
||||
if err = Access(s.diskPath); err == nil {
|
||||
// Disk is present but missing `format.json`
|
||||
return "", errUnformattedDisk
|
||||
}
|
||||
@@ -623,7 +621,7 @@ func (s *xlStorage) MakeVol(ctx context.Context, volume string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := Lstat(volumeDir); err != nil {
|
||||
if err = Access(volumeDir); err != nil {
|
||||
// Volume does not exist we proceed to create.
|
||||
if osIsNotExist(err) {
|
||||
// Make a volume entry, with mode 0777 mkdir honors system umask.
|
||||
@@ -675,6 +673,7 @@ func (s *xlStorage) StatVol(ctx context.Context, volume string) (vol VolInfo, er
|
||||
if err != nil {
|
||||
return VolInfo{}, err
|
||||
}
|
||||
|
||||
// Stat a volume entry.
|
||||
var st os.FileInfo
|
||||
st, err = Lstat(volumeDir)
|
||||
@@ -736,8 +735,7 @@ func (s *xlStorage) isLeaf(volume string, leafPath string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
_, err = Lstat(pathJoin(volumeDir, leafPath, xlStorageFormatFile))
|
||||
if err == nil {
|
||||
if err = Access(pathJoin(volumeDir, leafPath, xlStorageFormatFile)); err == nil {
|
||||
return true
|
||||
}
|
||||
if osIsNotExist(err) {
|
||||
@@ -767,10 +765,10 @@ func (s *xlStorage) ListDir(ctx context.Context, volume, dirPath string, count i
|
||||
}
|
||||
if err != nil {
|
||||
if err == errFileNotFound {
|
||||
if _, verr := Lstat(volumeDir); verr != nil {
|
||||
if osIsNotExist(verr) {
|
||||
if ierr := Access(volumeDir); ierr != nil {
|
||||
if osIsNotExist(ierr) {
|
||||
return nil, errVolumeNotFound
|
||||
} else if isSysErrIO(verr) {
|
||||
} else if isSysErrIO(ierr) {
|
||||
return nil, errFaultyDisk
|
||||
}
|
||||
}
|
||||
@@ -1042,8 +1040,7 @@ func (s *xlStorage) readAllData(volumeDir string, filePath string, requireDirect
|
||||
if osIsNotExist(err) {
|
||||
// Check if the object doesn't exist because its bucket
|
||||
// is missing in order to return the correct error.
|
||||
_, err = Lstat(volumeDir)
|
||||
if err != nil && osIsNotExist(err) {
|
||||
if err = Access(volumeDir); err != nil && osIsNotExist(err) {
|
||||
return nil, errVolumeNotFound
|
||||
}
|
||||
return nil, errFileNotFound
|
||||
@@ -1129,12 +1126,13 @@ func (s *xlStorage) ReadFile(ctx context.Context, volume string, path string, of
|
||||
var n int
|
||||
|
||||
// Stat a volume entry.
|
||||
_, err = Lstat(volumeDir)
|
||||
if err != nil {
|
||||
if err = Access(volumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return 0, errVolumeNotFound
|
||||
} else if isSysErrIO(err) {
|
||||
return 0, errFaultyDisk
|
||||
} else if osIsPermission(err) {
|
||||
return 0, errFileAccessDenied
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
@@ -1329,8 +1327,7 @@ func (s *xlStorage) ReadFileStream(ctx context.Context, volume, path string, off
|
||||
if err != nil {
|
||||
switch {
|
||||
case osIsNotExist(err):
|
||||
_, err = Lstat(volumeDir)
|
||||
if err != nil && osIsNotExist(err) {
|
||||
if err = Access(volumeDir); err != nil && osIsNotExist(err) {
|
||||
return nil, errVolumeNotFound
|
||||
}
|
||||
return nil, errFileNotFound
|
||||
@@ -1530,9 +1527,13 @@ func (s *xlStorage) AppendFile(ctx context.Context, volume string, path string,
|
||||
}
|
||||
|
||||
// Stat a volume entry.
|
||||
if _, err = Lstat(volumeDir); err != nil {
|
||||
if err = Access(volumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if osIsPermission(err) {
|
||||
return errVolumeAccessDenied
|
||||
} else if isSysErrIO(err) {
|
||||
return errFaultyDisk
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1571,7 +1572,7 @@ func (s *xlStorage) CheckParts(ctx context.Context, volume string, path string,
|
||||
}
|
||||
|
||||
// Stat a volume entry.
|
||||
if _, err = Lstat(volumeDir); err != nil {
|
||||
if err = Access(volumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
}
|
||||
@@ -1721,8 +1722,7 @@ func (s *xlStorage) Delete(ctx context.Context, volume string, path string, recu
|
||||
}
|
||||
|
||||
// Stat a volume entry.
|
||||
_, err = Lstat(volumeDir)
|
||||
if err != nil {
|
||||
if err = Access(volumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if osIsPermission(err) {
|
||||
@@ -1757,8 +1757,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath, dataDir,
|
||||
}
|
||||
|
||||
// Stat a volume entry.
|
||||
_, err = Lstat(srcVolumeDir)
|
||||
if err != nil {
|
||||
if err = Access(srcVolumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if isSysErrIO(err) {
|
||||
@@ -1767,7 +1766,7 @@ func (s *xlStorage) RenameData(ctx context.Context, srcVolume, srcPath, dataDir,
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = Lstat(dstVolumeDir); err != nil {
|
||||
if err = Access(dstVolumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if isSysErrIO(err) {
|
||||
@@ -1998,8 +1997,7 @@ func (s *xlStorage) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolum
|
||||
return err
|
||||
}
|
||||
// Stat a volume entry.
|
||||
_, err = Lstat(srcVolumeDir)
|
||||
if err != nil {
|
||||
if err = Access(srcVolumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if isSysErrIO(err) {
|
||||
@@ -2007,8 +2005,8 @@ func (s *xlStorage) RenameFile(ctx context.Context, srcVolume, srcPath, dstVolum
|
||||
}
|
||||
return err
|
||||
}
|
||||
_, err = Lstat(dstVolumeDir)
|
||||
if err != nil {
|
||||
|
||||
if err = Access(dstVolumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if isSysErrIO(err) {
|
||||
@@ -2142,8 +2140,7 @@ func (s *xlStorage) VerifyFile(ctx context.Context, volume, path string, fi File
|
||||
}
|
||||
|
||||
// Stat a volume entry.
|
||||
_, err = Lstat(volumeDir)
|
||||
if err != nil {
|
||||
if err = Access(volumeDir); err != nil {
|
||||
if osIsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
} else if isSysErrIO(err) {
|
||||
|
||||
@@ -869,7 +869,7 @@ func TestXLStorageListDir(t *testing.T) {
|
||||
var dirList []string
|
||||
dirList, err = xlStorage.ListDir(context.Background(), testCase.srcVol, testCase.srcPath, -1)
|
||||
if err != testCase.expectedErr {
|
||||
t.Fatalf("TestXLStorage case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err)
|
||||
t.Errorf("TestXLStorage case %d: Expected: \"%s\", got: \"%s\"", i+1, testCase.expectedErr, err)
|
||||
}
|
||||
if err == nil {
|
||||
for _, expected := range testCase.expectedListDir {
|
||||
@@ -900,8 +900,8 @@ func TestXLStorageListDir(t *testing.T) {
|
||||
t.Fatalf("Unable to initialize xlStorage, %s", err)
|
||||
}
|
||||
|
||||
if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", false); err != errFileAccessDenied {
|
||||
t.Errorf("expected: %s, got: %s", errFileAccessDenied, err)
|
||||
if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", false); err != errVolumeAccessDenied {
|
||||
t.Errorf("expected: %s, got: %s", errVolumeAccessDenied, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -915,6 +915,10 @@ func TestXLStorageListDir(t *testing.T) {
|
||||
|
||||
// TestXLStorageDeleteFile - Series of test cases construct valid and invalid input data and validates the result and the error response.
|
||||
func TestXLStorageDeleteFile(t *testing.T) {
|
||||
if runtime.GOOS == globalWindowsOSName {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
// create xlStorage test setup
|
||||
xlStorage, path, err := newXLStorageTestSetup()
|
||||
if err != nil {
|
||||
@@ -994,7 +998,7 @@ func TestXLStorageDeleteFile(t *testing.T) {
|
||||
{
|
||||
srcVol: "no-permissions",
|
||||
srcPath: "dir/file",
|
||||
expectedErr: nil,
|
||||
expectedErr: errVolumeAccessDenied,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1024,8 +1028,8 @@ func TestXLStorageDeleteFile(t *testing.T) {
|
||||
t.Fatalf("Unable to initialize xlStorage, %s", err)
|
||||
}
|
||||
|
||||
if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", false); err != errFileAccessDenied {
|
||||
t.Errorf("expected: %s, got: %s", errFileAccessDenied, err)
|
||||
if err = xlStorageNew.Delete(context.Background(), "mybucket", "myobject", false); err != errVolumeAccessDenied {
|
||||
t.Errorf("expected: %s, got: %s", errVolumeAccessDenied, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1401,8 +1405,8 @@ func TestXLStorageAppendFile(t *testing.T) {
|
||||
t.Fatalf("Unable to initialize xlStorage, %s", err)
|
||||
}
|
||||
|
||||
if err = xlStoragePermStorage.AppendFile(context.Background(), "mybucket", "myobject", []byte("hello, world")); err != errFileAccessDenied {
|
||||
t.Fatalf("expected: Permission error, got: %s", err)
|
||||
if err = xlStoragePermStorage.AppendFile(context.Background(), "mybucket", "myobject", []byte("hello, world")); err != errVolumeAccessDenied {
|
||||
t.Fatalf("expected: errVolumeAccessDenied error, got: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user