mirror of
https://github.com/minio/minio.git
synced 2025-11-20 01:50:24 -05:00
Avoid network transfer for bitrot verification during healing (#7375)
This commit is contained in:
committed by
Dee Koder
parent
e857b6741d
commit
58d90ed73c
103
cmd/posix.go
103
cmd/posix.go
@@ -958,7 +958,7 @@ func (s *posix) ReadFile(volume, path string, offset int64, buffer []byte, verif
|
||||
}
|
||||
|
||||
if !bytes.Equal(h.Sum(nil), verifier.sum) {
|
||||
return 0, hashMismatchError{hex.EncodeToString(verifier.sum), hex.EncodeToString(h.Sum(nil))}
|
||||
return 0, HashMismatchError{hex.EncodeToString(verifier.sum), hex.EncodeToString(h.Sum(nil))}
|
||||
}
|
||||
|
||||
return int64(len(buffer)), nil
|
||||
@@ -1525,3 +1525,104 @@ func (s *posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err e
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *posix) VerifyFile(volume, path string, algo BitrotAlgorithm, sum []byte, shardSize int64) (err error) {
|
||||
defer func() {
|
||||
if err == errFaultyDisk {
|
||||
atomic.AddInt32(&s.ioErrCount, 1)
|
||||
}
|
||||
}()
|
||||
|
||||
if atomic.LoadInt32(&s.ioErrCount) > maxAllowedIOError {
|
||||
return errFaultyDisk
|
||||
}
|
||||
|
||||
if err = s.checkDiskFound(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
volumeDir, err := s.getVolDir(volume)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Stat a volume entry.
|
||||
_, err = os.Stat((volumeDir))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errVolumeNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate effective path length before reading.
|
||||
filePath := pathJoin(volumeDir, path)
|
||||
if err = checkPathLength((filePath)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Open the file for reading.
|
||||
file, err := os.Open((filePath))
|
||||
if err != nil {
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
return errFileNotFound
|
||||
case os.IsPermission(err):
|
||||
return errFileAccessDenied
|
||||
case isSysErrNotDir(err):
|
||||
return errFileAccessDenied
|
||||
case isSysErrIO(err):
|
||||
return errFaultyDisk
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file descriptor.
|
||||
defer file.Close()
|
||||
|
||||
if algo != HighwayHash256S {
|
||||
bufp := s.pool.Get().(*[]byte)
|
||||
defer s.pool.Put(bufp)
|
||||
|
||||
h := algo.New()
|
||||
if _, err = io.CopyBuffer(h, file, *bufp); err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(h.Sum(nil), sum) {
|
||||
return HashMismatchError{hex.EncodeToString(sum), hex.EncodeToString(h.Sum(nil))}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
buf := make([]byte, shardSize)
|
||||
h := algo.New()
|
||||
hashBuf := make([]byte, h.Size())
|
||||
fi, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
size := fi.Size()
|
||||
for {
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
h.Reset()
|
||||
n, err := file.Read(hashBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
size -= int64(n)
|
||||
if size < int64(len(buf)) {
|
||||
buf = buf[:size]
|
||||
}
|
||||
n, err = file.Read(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
size -= int64(n)
|
||||
h.Write(buf)
|
||||
if !bytes.Equal(h.Sum(nil), hashBuf) {
|
||||
return HashMismatchError{hex.EncodeToString(hashBuf), hex.EncodeToString(h.Sum(nil))}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user