diff --git a/src/restic/backend/s3/s3.go b/src/restic/backend/s3/s3.go index d5e537e5a..684588164 100644 --- a/src/restic/backend/s3/s3.go +++ b/src/restic/backend/s3/s3.go @@ -7,6 +7,7 @@ import ( "path" "restic" "strings" + "sync" "restic/backend" "restic/errors" @@ -24,8 +25,8 @@ type s3 struct { connChan chan struct{} bucketname string prefix string - cacheObjName string - cacheSize int64 + cacheMutex sync.RWMutex + cacheObjSize map[string]int64 } // Open opens the S3 backend at bucket and region. The bucket is created if it @@ -38,7 +39,12 @@ func Open(cfg Config) (restic.Backend, error) { return nil, errors.Wrap(err, "minio.New") } - be := &s3{client: client, bucketname: cfg.Bucket, prefix: cfg.Prefix} + be := &s3{ + client: client, + bucketname: cfg.Bucket, + prefix: cfg.Prefix, + cacheObjSize: make(map[string]int64), + } tr := &http.Transport{MaxIdleConnsPerHost: connLimit} client.SetCustomTransport(tr) @@ -189,17 +195,20 @@ func (be *s3) Load(h restic.Handle, length int, offset int64) (io.ReadCloser, er }() // otherwise use a buffer with ReadAt - if be.cacheObjName == objName { - size = be.cacheSize - } else { + be.cacheMutex.RLock() + size, cacheHit := be.cacheObjSize[objName] + be.cacheMutex.RUnlock() + + if !cacheHit { info, err := obj.Stat() if err != nil { _ = obj.Close() return nil, errors.Wrap(err, "obj.Stat") } size = info.Size - be.cacheObjName = objName - be.cacheSize = size + be.cacheMutex.Lock() + be.cacheObjSize[objName] = size + be.cacheMutex.Unlock() } if offset > size {