Add server pool reserved space (#14974)

If one or more pools reach 85% usage in a set, we will only 
use pools that have more free space.

In case all pools are above 85% we allow all of them to be used 
with the regular distribution.
This commit is contained in:
Klaus Post 2022-05-25 13:20:20 -07:00 committed by GitHub
parent d8101573be
commit a4be0b88f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 4 deletions

View File

@ -233,8 +233,9 @@ func (z *erasureServerPools) SetDriveCounts() []int {
type serverPoolsAvailableSpace []poolAvailableSpace type serverPoolsAvailableSpace []poolAvailableSpace
type poolAvailableSpace struct { type poolAvailableSpace struct {
Index int Index int
Available uint64 Available uint64
MaxUsedPct int // Used disk percentage of most filled disk, rounded down.
} }
// TotalAvailable - total available space // TotalAvailable - total available space
@ -246,10 +247,41 @@ func (p serverPoolsAvailableSpace) TotalAvailable() uint64 {
return total return total
} }
// FilterMaxUsed will filter out any pools that has used percent bigger than max,
// unless all have that, in which case all are preserved.
func (p serverPoolsAvailableSpace) FilterMaxUsed(max int) {
// We aren't modifying p, only entries in it, so we don't need to receive a pointer.
if len(p) <= 1 {
// Nothing to do.
return
}
var ok bool
for _, z := range p {
if z.MaxUsedPct < max {
ok = true
break
}
}
if !ok {
// All above limit.
// Do not modify
return
}
// Remove entries that are above.
for i, z := range p {
if z.MaxUsedPct < max {
continue
}
p[i].Available = 0
}
}
// getAvailablePoolIdx will return an index that can hold size bytes. // getAvailablePoolIdx will return an index that can hold size bytes.
// -1 is returned if no serverPools have available space for the size given. // -1 is returned if no serverPools have available space for the size given.
func (z *erasureServerPools) getAvailablePoolIdx(ctx context.Context, bucket, object string, size int64) int { func (z *erasureServerPools) getAvailablePoolIdx(ctx context.Context, bucket, object string, size int64) int {
serverPools := z.getServerPoolsAvailableSpace(ctx, bucket, object, size) serverPools := z.getServerPoolsAvailableSpace(ctx, bucket, object, size)
serverPools.FilterMaxUsed(100 - (100 * diskReserveFraction))
total := serverPools.TotalAvailable() total := serverPools.TotalAvailable()
if total == 0 { if total == 0 {
return -1 return -1
@ -302,11 +334,17 @@ func (z *erasureServerPools) getServerPoolsAvailableSpace(ctx context.Context, b
serverPools[i] = poolAvailableSpace{Index: i} serverPools[i] = poolAvailableSpace{Index: i}
continue continue
} }
var maxUsedPct int
for _, disk := range zinfo { for _, disk := range zinfo {
if disk == nil { if disk == nil {
continue continue
} }
available += disk.Total - disk.Used available += disk.Total - disk.Used
// set maxUsedPct to the value from the disk with the least space percentage.
if pctUsed := int(disk.Used * 100 / disk.Total); pctUsed > maxUsedPct {
maxUsedPct = pctUsed
}
} }
// Since we are comparing pools that may have a different number of sets // Since we are comparing pools that may have a different number of sets
@ -317,8 +355,9 @@ func (z *erasureServerPools) getServerPoolsAvailableSpace(ctx context.Context, b
available *= uint64(nSets[i]) available *= uint64(nSets[i])
serverPools[i] = poolAvailableSpace{ serverPools[i] = poolAvailableSpace{
Index: i, Index: i,
Available: available, Available: available,
MaxUsedPct: maxUsedPct,
} }
} }
return serverPools return serverPools

View File

@ -113,6 +113,10 @@ const (
// diskFillFraction is the fraction of a disk we allow to be filled. // diskFillFraction is the fraction of a disk we allow to be filled.
diskFillFraction = 0.99 diskFillFraction = 0.99
// diskReserveFraction is the fraction of a disk where we will fill other server pools first.
// If all pools reach this, we will use all pools with regular placement.
diskReserveFraction = 0.15
// diskAssumeUnknownSize is the size to assume when an unknown size upload is requested. // diskAssumeUnknownSize is the size to assume when an unknown size upload is requested.
diskAssumeUnknownSize = 1 << 30 diskAssumeUnknownSize = 1 << 30