mirror of
https://github.com/minio/minio.git
synced 2025-02-05 10:48:07 -05:00
s3: Provide enough buffer when the object final size is unknown (#20847)
When compression is enabled, the final object size is not calculated in that case, we need to make sure that the provided buffer is always more significant than the shard size, the bitrot will always calculate the hash of blocks with shard size, except the last block.
This commit is contained in:
parent
b9196757fd
commit
dbcb71828d
@ -20,6 +20,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"hash"
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
@ -37,12 +38,22 @@ type streamingBitrotWriter struct {
|
|||||||
shardSize int64
|
shardSize int64
|
||||||
canClose *sync.WaitGroup
|
canClose *sync.WaitGroup
|
||||||
byteBuf []byte
|
byteBuf []byte
|
||||||
|
finished bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *streamingBitrotWriter) Write(p []byte) (int, error) {
|
func (b *streamingBitrotWriter) Write(p []byte) (int, error) {
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
if b.finished {
|
||||||
|
return 0, errors.New("bitrot write not allowed")
|
||||||
|
}
|
||||||
|
if int64(len(p)) > b.shardSize {
|
||||||
|
return 0, errors.New("unexpected bitrot buffer size")
|
||||||
|
}
|
||||||
|
if int64(len(p)) < b.shardSize {
|
||||||
|
b.finished = true
|
||||||
|
}
|
||||||
b.h.Reset()
|
b.h.Reset()
|
||||||
b.h.Write(p)
|
b.h.Write(p)
|
||||||
hashBytes := b.h.Sum(nil)
|
hashBytes := b.h.Sum(nil)
|
||||||
|
@ -626,17 +626,13 @@ func (er erasureObjects) PutObjectPart(ctx context.Context, bucket, object, uplo
|
|||||||
switch size := data.Size(); {
|
switch size := data.Size(); {
|
||||||
case size == 0:
|
case size == 0:
|
||||||
buffer = make([]byte, 1) // Allocate at least a byte to reach EOF
|
buffer = make([]byte, 1) // Allocate at least a byte to reach EOF
|
||||||
case size == -1:
|
case size >= fi.Erasure.BlockSize || size == -1:
|
||||||
if size := data.ActualSize(); size > 0 && size < fi.Erasure.BlockSize {
|
if int64(globalBytePoolCap.Load().Width()) < fi.Erasure.BlockSize {
|
||||||
// Account for padding and forced compression overhead and encryption.
|
buffer = make([]byte, fi.Erasure.BlockSize, 2*fi.Erasure.BlockSize)
|
||||||
buffer = make([]byte, data.ActualSize()+256+32+32, data.ActualSize()*2+512)
|
|
||||||
} else {
|
} else {
|
||||||
buffer = globalBytePoolCap.Load().Get()
|
buffer = globalBytePoolCap.Load().Get()
|
||||||
defer globalBytePoolCap.Load().Put(buffer)
|
defer globalBytePoolCap.Load().Put(buffer)
|
||||||
}
|
}
|
||||||
case size >= fi.Erasure.BlockSize:
|
|
||||||
buffer = globalBytePoolCap.Load().Get()
|
|
||||||
defer globalBytePoolCap.Load().Put(buffer)
|
|
||||||
case size < fi.Erasure.BlockSize:
|
case size < fi.Erasure.BlockSize:
|
||||||
// No need to allocate fully fi.Erasure.BlockSize buffer if the incoming data is smaller.
|
// No need to allocate fully fi.Erasure.BlockSize buffer if the incoming data is smaller.
|
||||||
buffer = make([]byte, size, 2*size+int64(fi.Erasure.ParityBlocks+fi.Erasure.DataBlocks-1))
|
buffer = make([]byte, size, 2*size+int64(fi.Erasure.ParityBlocks+fi.Erasure.DataBlocks-1))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user