mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-21 22:56:55 +00:00
fix(storage): use ceil division for EC shard slots in maxVolumeCount (#9196)
* fix(storage): use ceil division for EC shard slots in maxVolumeCount * fix(topology): use ceil division for EC shard slots consistently Applies the same ceiling-division formula used in store.go to the four remaining master-side sites that computed volume-slots consumed by EC shards with off-by-one approximations: - disk.go ToDiskInfo / Disk.ToDiskInfo used (n+1)/d, which under-counts slots for non-multiples of DataShardsCount, over-reporting FreeVolumeCount. - DiskUsageCounts.FreeSpace and NodeImpl.AvailableSpaceFor subtracted n/d + 1, which over-counts slots at multiples of DataShardsCount, under-reporting free space (and suppressing volume growth on nodes that still had room). All four now use (n + DataShardsCount - 1) / DataShardsCount, matching store.go:393, store.go:810, and command_ec_decode.go:422. * refactor(topology): extract ecShardSlots helper Deduplicates the (n + DataShardsCount - 1) / DataShardsCount ceiling expression now used by ToDiskInfo, DiskUsageCounts.FreeSpace, Disk.ToDiskInfo, and AvailableSpaceFor. Addresses PR review feedback. --------- Co-authored-by: Chris Lu <chris.lu@gmail.com>
This commit is contained in:
@@ -807,7 +807,7 @@ func (s *Store) MaybeAdjustVolumeMax() (hasChanges bool) {
|
||||
}
|
||||
volCount := diskLocation.VolumesLen()
|
||||
ecShardCount := diskLocation.EcShardCount()
|
||||
maxVolumeCount := int32(volCount) + int32((ecShardCount+erasure_coding.DataShardsCount)/erasure_coding.DataShardsCount)
|
||||
maxVolumeCount := int32(volCount) + int32((ecShardCount+erasure_coding.DataShardsCount-1)/erasure_coding.DataShardsCount)
|
||||
if unclaimedSpaces > int64(volumeSizeLimit) {
|
||||
maxVolumeCount += int32(uint64(unclaimedSpaces)/volumeSizeLimit) - 1
|
||||
}
|
||||
|
||||
@@ -23,6 +23,12 @@ type Disk struct {
|
||||
ecShardsLock sync.RWMutex
|
||||
}
|
||||
|
||||
// ecShardSlots returns the number of volume slots consumed by the given
|
||||
// number of EC shards, rounded up to whole-volume equivalents.
|
||||
func ecShardSlots(ecShardCount int64) int64 {
|
||||
return (ecShardCount + erasure_coding.DataShardsCount - 1) / erasure_coding.DataShardsCount
|
||||
}
|
||||
|
||||
func NewDisk(diskType string) *Disk {
|
||||
s := &Disk{}
|
||||
s.id = NodeId(diskType)
|
||||
@@ -67,7 +73,7 @@ func (d *DiskUsages) ToDiskInfo() map[string]*master_pb.DiskInfo {
|
||||
m := &master_pb.DiskInfo{
|
||||
VolumeCount: diskUsageCounts.volumeCount,
|
||||
MaxVolumeCount: diskUsageCounts.maxVolumeCount,
|
||||
FreeVolumeCount: diskUsageCounts.maxVolumeCount - (diskUsageCounts.volumeCount - diskUsageCounts.remoteVolumeCount) - (diskUsageCounts.ecShardCount+1)/erasure_coding.DataShardsCount,
|
||||
FreeVolumeCount: diskUsageCounts.maxVolumeCount - (diskUsageCounts.volumeCount - diskUsageCounts.remoteVolumeCount) - ecShardSlots(diskUsageCounts.ecShardCount),
|
||||
ActiveVolumeCount: diskUsageCounts.activeVolumeCount,
|
||||
RemoteVolumeCount: diskUsageCounts.remoteVolumeCount,
|
||||
}
|
||||
@@ -111,11 +117,7 @@ func (a *DiskUsageCounts) addDiskUsageCounts(b *DiskUsageCounts) {
|
||||
}
|
||||
|
||||
func (a *DiskUsageCounts) FreeSpace() int64 {
|
||||
freeVolumeSlotCount := a.maxVolumeCount + a.remoteVolumeCount - a.volumeCount
|
||||
if a.ecShardCount > 0 {
|
||||
freeVolumeSlotCount = freeVolumeSlotCount - a.ecShardCount/erasure_coding.DataShardsCount - 1
|
||||
}
|
||||
return freeVolumeSlotCount
|
||||
return a.maxVolumeCount + a.remoteVolumeCount - a.volumeCount - ecShardSlots(a.ecShardCount)
|
||||
}
|
||||
|
||||
func (du *DiskUsages) getOrCreateDisk(diskType types.DiskType) *DiskUsageCounts {
|
||||
@@ -265,7 +267,7 @@ func (d *Disk) ToDiskInfo() *master_pb.DiskInfo {
|
||||
Type: string(d.Id()),
|
||||
VolumeCount: diskUsage.volumeCount,
|
||||
MaxVolumeCount: diskUsage.maxVolumeCount,
|
||||
FreeVolumeCount: diskUsage.maxVolumeCount - (diskUsage.volumeCount - diskUsage.remoteVolumeCount) - (diskUsage.ecShardCount+1)/erasure_coding.DataShardsCount,
|
||||
FreeVolumeCount: diskUsage.maxVolumeCount - (diskUsage.volumeCount - diskUsage.remoteVolumeCount) - ecShardSlots(diskUsage.ecShardCount),
|
||||
ActiveVolumeCount: diskUsage.activeVolumeCount,
|
||||
RemoteVolumeCount: diskUsage.remoteVolumeCount,
|
||||
DiskId: diskId,
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/seaweedfs/seaweedfs/weed/glog"
|
||||
"github.com/seaweedfs/seaweedfs/weed/stats"
|
||||
"github.com/seaweedfs/seaweedfs/weed/storage/erasure_coding"
|
||||
"github.com/seaweedfs/seaweedfs/weed/storage/needle"
|
||||
"github.com/seaweedfs/seaweedfs/weed/storage/types"
|
||||
)
|
||||
@@ -272,10 +271,7 @@ func (n *NodeImpl) getOrCreateDisk(diskType types.DiskType) *DiskUsageCounts {
|
||||
func (n *NodeImpl) AvailableSpaceFor(option *VolumeGrowOption) int64 {
|
||||
t := n.getOrCreateDisk(option.DiskType)
|
||||
freeVolumeSlotCount := atomic.LoadInt64(&t.maxVolumeCount) + atomic.LoadInt64(&t.remoteVolumeCount) - atomic.LoadInt64(&t.volumeCount)
|
||||
ecShardCount := atomic.LoadInt64(&t.ecShardCount)
|
||||
if ecShardCount > 0 {
|
||||
freeVolumeSlotCount = freeVolumeSlotCount - ecShardCount/erasure_coding.DataShardsCount - 1
|
||||
}
|
||||
freeVolumeSlotCount -= ecShardSlots(atomic.LoadInt64(&t.ecShardCount))
|
||||
return freeVolumeSlotCount
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user