mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-22 06:22:38 +00:00
filer leveldb2: saturate size options instead of overflowing int
The option fields take int, so a MiB config value past math.MaxInt/MiB (e.g. 2048 on 32-bit) wrapped negative and goleveldb would panic sizing the memtable. Clamp the product instead of the input.
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
@@ -56,20 +57,29 @@ func (store *LevelDB2Store) buildOptions() *opt.Options {
|
||||
ReadOnly: store.ReadOnly,
|
||||
}
|
||||
if store.blockCacheSizeMB > 0 {
|
||||
opts.BlockCacheCapacity = store.blockCacheSizeMB * 1024 * 1024
|
||||
opts.BlockCacheCapacity = scaled(store.blockCacheSizeMB, 1<<20)
|
||||
}
|
||||
if store.writeBufferSizeMB > 0 {
|
||||
opts.WriteBuffer = store.writeBufferSizeMB * 1024 * 1024
|
||||
opts.WriteBuffer = scaled(store.writeBufferSizeMB, 1<<20)
|
||||
}
|
||||
if store.blockSizeKB > 0 {
|
||||
opts.BlockSize = store.blockSizeKB * 1024
|
||||
opts.BlockSize = scaled(store.blockSizeKB, 1<<10)
|
||||
}
|
||||
if store.compactionTableSizeMB > 0 {
|
||||
opts.CompactionTableSize = store.compactionTableSizeMB * 1024 * 1024
|
||||
opts.CompactionTableSize = scaled(store.compactionTableSizeMB, 1<<20)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
// scaled converts a size option to bytes, saturating instead of wrapping a
|
||||
// huge value into a negative int on 32-bit builds.
|
||||
func scaled(v, scale int) int {
|
||||
if v > math.MaxInt/scale {
|
||||
return math.MaxInt
|
||||
}
|
||||
return v * scale
|
||||
}
|
||||
|
||||
func (store *LevelDB2Store) initialize(dir string, dbCount int) (err error) {
|
||||
glog.Infof("filer store leveldb2 dir: %s", dir)
|
||||
os.MkdirAll(dir, 0755)
|
||||
|
||||
@@ -2,6 +2,7 @@ package leveldb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/filer"
|
||||
@@ -138,6 +139,18 @@ func TestInitializeDefaultOptions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScaledSaturates(t *testing.T) {
|
||||
if got := scaled(math.MaxInt, 1<<20); got != math.MaxInt {
|
||||
t.Errorf("expected saturation at %d, got %d", math.MaxInt, got)
|
||||
}
|
||||
if got := scaled(64, 1<<20); got != 64*1024*1024 {
|
||||
t.Errorf("expected 64MiB, got %d", got)
|
||||
}
|
||||
if got := scaled(4, 1<<10); got != 4*1024 {
|
||||
t.Errorf("expected 4KiB, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyRoot(t *testing.T) {
|
||||
testFiler := filer.NewFiler(pb.ServerDiscovery{}, nil, "", "", "", "", "", 255, nil)
|
||||
dir := t.TempDir()
|
||||
|
||||
Reference in New Issue
Block a user