@@ -36,6 +36,7 @@ import (
3636 "github.com/minio/minio-go/v7/pkg/tags"
3737 "github.com/minio/minio/pkg/bucket/policy"
3838 "github.com/minio/minio/pkg/madmin"
39+ "golang.org/x/sync/errgroup"
3940
4041 "github.com/google/uuid"
4142 "github.com/minio/minio-go/v7/pkg/s3utils"
@@ -1161,7 +1162,28 @@ func (n *jfsObjects) CompleteMultipartUpload(ctx context.Context, bucket, object
11611162 if err = n .checkUploadIDExists (ctx , bucket , object , uploadID ); err != nil {
11621163 return
11631164 }
1164-
1165+ g , ectx := errgroup .WithContext (ctx )
1166+ g .SetLimit (10 )
1167+ for i := 0 ; i < len (parts ); i ++ {
1168+ i := i
1169+ g .Go (func () error {
1170+ select {
1171+ case <- ectx .Done ():
1172+ return ectx .Err ()
1173+ default :
1174+ }
1175+ ppath := n .ppath (bucket , uploadID , strconv .Itoa (parts [i ].PartNumber ))
1176+ etag , _ := n .fs .GetXattr (mctx , ppath , s3Etag )
1177+ if string (etag ) != "" && string (etag ) != parts [i ].ETag {
1178+ logger .Warnf ("path: %s,expect etag: %s,but got: %s" , ppath , etag , parts [i ].ETag )
1179+ return minio .ErrInvalidEtag
1180+ }
1181+ return nil
1182+ })
1183+ }
1184+ if err = g .Wait (); err != nil {
1185+ return objInfo , err
1186+ }
11651187 tmp := n .ppath (bucket , uploadID , "complete" )
11661188 _ = n .fs .Delete (mctx , tmp )
11671189 f , eno := n .fs .Create (mctx , tmp , 0666 , n .gConf .Umask )
0 commit comments