s3api: fix multipart Complete ETag matching and lower empty-upload log noise (#8264)

s3api: fix multipart part etag validation and reduce empty upload warning noise
This commit is contained in:
Chris Lu
2026-02-09 11:45:57 -08:00
committed by GitHub
parent d9987669cb
commit 59b02e0cba
3 changed files with 84 additions and 11 deletions

View File

@@ -243,17 +243,16 @@ func (s3a *S3ApiServer) completeMultipartUpload(r *http.Request, input *s3.Compl
continue
}
for _, partETag := range completedPartsByNumber {
partETag = strings.Trim(partETag, `"`)
entryETag := hex.EncodeToString(entry.Attributes.GetMd5())
if partETag != "" && len(partETag) == 32 && entryETag != "" {
if entryETag != partETag {
glog.Errorf("completeMultipartUpload %s ETag mismatch chunk: %s part: %s", entry.Name, entryETag, partETag)
stats.S3HandlerCounter.WithLabelValues(stats.ErrorCompletedEtagMismatch).Inc()
continue
}
} else {
glog.Warningf("invalid complete etag %s, partEtag %s", partETag, entryETag)
match, invalid, normalizedPartETag, normalizedEntryETag := validateCompletePartETag(partETag, entry)
if invalid {
glog.Warningf("invalid complete etag %s, storedEtag %s", normalizedPartETag, normalizedEntryETag)
stats.S3HandlerCounter.WithLabelValues(stats.ErrorCompletedEtagInvalid).Inc()
continue
}
if !match {
glog.Errorf("completeMultipartUpload %s ETag mismatch stored: %s part: %s", entry.Name, normalizedEntryETag, normalizedPartETag)
stats.S3HandlerCounter.WithLabelValues(stats.ErrorCompletedEtagMismatch).Inc()
continue
}
if len(entry.Chunks) == 0 && partNumber != maxPartNo {
glog.Warningf("completeMultipartUpload %s empty chunks", entry.Name)
@@ -1001,3 +1000,17 @@ func getEtagFromEntry(entry *filer_pb.Entry) string {
glog.V(4).Infof("getEtagFromEntry: fallback to filer.ETag for %s: %s, chunkCount: %d", entryName, etag, len(entry.Chunks))
return "\"" + etag + "\""
}
func validateCompletePartETag(partETag string, entry *filer_pb.Entry) (match bool, invalid bool, normalizedPartETag string, normalizedEntryETag string) {
normalizedPartETag = strings.Trim(strings.TrimSpace(partETag), `"`)
if normalizedPartETag == "" {
return false, true, normalizedPartETag, ""
}
normalizedEntryETag = strings.Trim(getEtagFromEntry(entry), `"`)
if normalizedEntryETag == "" {
return false, true, normalizedPartETag, normalizedEntryETag
}
return normalizedPartETag == normalizedEntryETag, false, normalizedPartETag, normalizedEntryETag
}