fs: ListObjects() was reading ETag at wrong offsets (#4846)

Current code was just using io.ReadAll() on an fd()
which might have moved underneath due to a concurrent
read operation. Subsequent read will result in EOF
We should always seek back and read again. pread()
is allowed on all platforms use io.SectionReader to
read from the beginning of the file.

Fixes #4842
master
Harshavardhana 7 years ago committed by Dee Koder
parent db5af1b126
commit 1bb9d49eaa
  1. 25
      cmd/fs-v1.go

@ -749,14 +749,24 @@ func (fs fsObjects) getObjectETag(bucket, entry string) (string, error) {
// Read from fs metadata only if it exists.
defer fs.rwPool.Close(fsMetaPath)
fsMetaBuf, err := ioutil.ReadAll(rlk.LockedFile)
// Fetch the size of the underlying file.
fi, err := rlk.LockedFile.Stat()
if err != nil {
// `fs.json` can be empty due to previously failed
// PutObject() transaction, if we arrive at such
// a situation we just ignore and continue.
if errorCause(err) != io.EOF {
return "", toObjectErr(err, bucket, entry)
}
return "", toObjectErr(traceError(err), bucket, entry)
}
// `fs.json` can be empty due to previously failed
// PutObject() transaction, if we arrive at such
// a situation we just ignore and continue.
if fi.Size() == 0 {
return "", nil
}
// Wrap the locked file in a ReadAt() backend section reader to
// make sure the underlying offsets don't move.
fsMetaBuf, err := ioutil.ReadAll(io.NewSectionReader(rlk.LockedFile, 0, fi.Size()))
if err != nil {
return "", traceError(err)
}
// Check if FS metadata is valid, if not return error.
@ -876,6 +886,7 @@ func (fs fsObjects) ListObjects(bucket, prefix, marker, delimiter string, maxKey
}
objInfo, err := entryToObjectInfo(walkResult.entry)
if err != nil {
errorIf(err, "Unable to fetch object info for %s", walkResult.entry)
return loi, nil
}
nextMarker = objInfo.Name

Loading…
Cancel
Save