Skip to content

Commit 38d2f9a

Browse files
committed
fix: move live Statfs to RemainingResources; use *uint64 for min-free config
- TotalResources reverts to static startup value to keep total-remaining arithmetic consistent for BBS metrics - RemainingResources caps reported DiskMB at live partition free space (syscall.Statfs), so schedulers see reduced capacity when disk fills - MinCachePartitionFreeBytes changed to *uint64: nil means use the 5 GB default, 0 explicitly disables the check (previously impossible) ai-assisted=yes TNZ-111552
1 parent 66e26d2 commit 38d2f9a

13 files changed

Lines changed: 114 additions & 50 deletions

File tree

jobs/rep/spec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ properties:
147147
diego.executor.max_cache_size_in_bytes:
148148
description: "maximum size of the cache in bytes - this should leave a healthy overhead for temporary items, etc."
149149
default: 10000000000
150+
diego.executor.min_cache_partition_free_bytes:
151+
description: "Minimum free space in bytes that must remain on the disk where the download cache lives. When actual disk free space falls below this threshold, the cache deletes old downloaded files to recover space. Uses live partition statistics rather than in-memory accounting. Defaults to 5368709120 (5 GB) if unset."
150152
diego.executor.use_schedulable_disk_size:
151153
description: "Use total space available to containers reported by Garden. If false the total size of image plugin store minus max_cache_size_in_bytes is used."
152154
default: false

jobs/rep/templates/rep.json.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@
125125
raise "additional_memory_allocation_mb cannot be negative"
126126
end
127127

128+
if_p("diego.executor.min_cache_partition_free_bytes") do |value|
129+
config[:min_cache_partition_free_bytes] = value
130+
end
131+
128132
if_p("diego.executor.volman.driver_paths") do |value|
129133
config[:volman_driver_paths] = value
130134
end

jobs/rep_windows/spec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ properties:
129129
diego.executor.max_cache_size_in_bytes:
130130
description: "maximum size of the cache in bytes - this should leave a healthy overhead for temporary items, etc."
131131
default: 10000000000
132+
diego.executor.min_cache_partition_free_bytes:
133+
description: "Minimum free space in bytes that must remain on the disk where the download cache lives. When actual disk free space falls below this threshold, the cache deletes old downloaded files to recover space. Currently does not function on Windows cells. Defaults to 5368709120 (5 GB) if unset."
132134
diego.executor.use_schedulable_disk_size:
133135
description: "Use total space available to containers reported by Garden. If false the total size of image plugin store minus max_cache_size_in_bytes is used."
134136
default: false

jobs/rep_windows/templates/rep.json.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@
122122
raise "additional_memory_allocation_mb cannot be negative"
123123
end
124124

125+
if_p("diego.executor.min_cache_partition_free_bytes") do |value|
126+
config[:min_cache_partition_free_bytes] = value
127+
end
128+
125129
if_p("diego.executor.volman.driver_paths") do |value|
126130
config[:volman_driver_paths] = value
127131
end

src/code.cloudfoundry.org/cacheddownloader/file_cache.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ import (
44
"errors"
55
"fmt"
66
"io"
7-
"math"
87
"os"
98
"path/filepath"
109
"sync"
11-
"syscall"
1210
"time"
1311

1412
"code.cloudfoundry.org/archiver/compressor"
@@ -34,14 +32,6 @@ type FileCache struct {
3432
Seq uint64
3533
}
3634

37-
func defaultFreeSpaceOnPartition(path string) int64 {
38-
var stat syscall.Statfs_t
39-
if err := syscall.Statfs(path, &stat); err != nil {
40-
return math.MaxInt64
41-
}
42-
return int64(stat.Bavail) * int64(stat.Bsize)
43-
}
44-
4535
type FileCacheEntry struct {
4636
Size int64
4737
Access time.Time
@@ -201,6 +191,11 @@ func (e *FileCacheEntry) expandedDirectory() (string, error) {
201191
err = os.RemoveAll(e.FilePath)
202192
if err != nil {
203193
fmt.Fprintln(os.Stderr, "Unable to delete the cached file", err)
194+
} else {
195+
// GetDirectory doubled Size before calling here; tar is now gone so halve it
196+
// back to reflect only the .tar.d on disk. Mirrors the symmetric halving in
197+
// decrementFileInUseCount() which fires when the tar is deleted later.
198+
e.Size = e.Size / 2
204199
}
205200
}
206201
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build !windows
2+
3+
package cacheddownloader
4+
5+
import (
6+
"math"
7+
"syscall"
8+
)
9+
10+
func defaultFreeSpaceOnPartition(path string) int64 {
11+
var stat syscall.Statfs_t
12+
if err := syscall.Statfs(path, &stat); err != nil {
13+
return math.MaxInt64
14+
}
15+
return int64(stat.Bavail) * int64(stat.Bsize)
16+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build windows
2+
3+
package cacheddownloader
4+
5+
import "math"
6+
7+
func defaultFreeSpaceOnPartition(path string) int64 {
8+
return math.MaxInt64
9+
}

src/code.cloudfoundry.org/executor/depot/depot.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,29 @@ func (c *client) DeleteContainer(logger lager.Logger, traceID string, guid strin
219219

220220
func (c *client) RemainingResources(logger lager.Logger) (executor.ExecutorResources, error) {
221221
logger = logger.Session("remaining-resources")
222-
return c.containerStore.RemainingResources(logger), nil
222+
remaining := c.containerStore.RemainingResources(logger)
223+
if c.diskPath != "" {
224+
if liveMB, ok := liveDiskMB(c.diskPath); ok && liveMB < remaining.DiskMB {
225+
remaining.DiskMB = liveMB
226+
}
227+
}
228+
return remaining, nil
223229
}
224230

225231
func (c *client) Ping(logger lager.Logger) error {
226232
return c.gardenClient.Ping()
227233
}
228234

229235
func (c *client) TotalResources(logger lager.Logger) (executor.ExecutorResources, error) {
236+
diskMB := c.totalCapacity.DiskMB
237+
if c.diskPath != "" {
238+
if liveMB, ok := liveDiskMB(c.diskPath); ok {
239+
diskMB = liveMB
240+
}
241+
}
230242
return executor.ExecutorResources{
231243
MemoryMB: c.totalCapacity.MemoryMB,
232-
DiskMB: getDiskMB(c.diskPath, c.totalCapacity.DiskMB),
244+
DiskMB: diskMB,
233245
Containers: c.totalCapacity.Containers,
234246
}, nil
235247
}

src/code.cloudfoundry.org/executor/depot/depot_test.go

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -698,45 +698,70 @@ var _ = Describe("Depot", func() {
698698
})
699699

700700
Describe("RemainingResources", func() {
701-
var resources executor.ExecutorResources
701+
var remainingResources executor.ExecutorResources
702702

703703
BeforeEach(func() {
704-
resources = executor.NewExecutorResources(1024, 1024, 3)
705-
containerStore.RemainingResourcesReturns(resources)
704+
remainingResources = executor.NewExecutorResources(1024, 1024, 3)
705+
containerStore.RemainingResourcesReturns(remainingResources)
706706
})
707707

708708
It("should reduce resources used by allocated and running containers", func() {
709709
actualResources, err := depotClient.RemainingResources(logger)
710710
Expect(err).NotTo(HaveOccurred())
711-
Expect(actualResources).To(Equal(resources))
711+
Expect(actualResources).To(Equal(remainingResources))
712+
})
713+
714+
Context("when disk path is configured and partition has less space than the store reports", func() {
715+
var tmpDir string
716+
717+
BeforeEach(func() {
718+
var err error
719+
tmpDir, err = os.MkdirTemp("", "depot-remaining-disk-test")
720+
Expect(err).NotTo(HaveOccurred())
721+
diskPath = tmpDir
722+
containerStore.RemainingResourcesReturns(executor.NewExecutorResources(1024, math.MaxInt32, 3))
723+
})
724+
725+
It("caps remaining disk at the live partition free space from syscall.Statfs", func() {
726+
result, err := depotClient.RemainingResources(logger)
727+
Expect(err).NotTo(HaveOccurred())
728+
Expect(result.DiskMB).NotTo(Equal(math.MaxInt32))
729+
Expect(result.DiskMB).To(BeNumerically(">", 0))
730+
})
712731
})
713732
})
714733

715734
Describe("TotalResources", func() {
716-
Context("when asked for total resources", func() {
717-
Context("when disk path is not provided", func() {
718-
It("should return the resources it was configured with", func() {
719-
Expect(depotClient.TotalResources(logger)).To(Equal(resources))
720-
})
735+
Context("when no disk path is configured", func() {
736+
It("returns the static startup resources", func() {
737+
result, err := depotClient.TotalResources(logger)
738+
Expect(err).NotTo(HaveOccurred())
739+
Expect(result).To(Equal(resources))
721740
})
741+
})
722742

723-
Context("when disk path is provided", func() {
724-
BeforeEach(func() {
725-
diskPath = os.TempDir()
726-
})
743+
Context("when disk path is configured", func() {
744+
var tmpDir string
727745

728-
It("should return the resources it was configured with, with live disk capacity", func() {
729-
totalResources, err := depotClient.TotalResources(logger)
730-
Expect(err).NotTo(HaveOccurred())
746+
BeforeEach(func() {
747+
var err error
748+
tmpDir, err = os.MkdirTemp("", "depot-total-disk-test")
749+
Expect(err).NotTo(HaveOccurred())
750+
diskPath = tmpDir
751+
resources.DiskMB = math.MaxInt32
752+
})
731753

732-
Expect(totalResources.MemoryMB).To(Equal(resources.MemoryMB))
733-
Expect(totalResources.Containers).To(Equal(resources.Containers))
754+
AfterEach(func() {
755+
os.RemoveAll(tmpDir)
756+
})
734757

735-
// disk capacity should be updated
736-
Expect(totalResources.DiskMB).NotTo(Equal(resources.DiskMB))
737-
Expect(totalResources.DiskMB).To(BeNumerically(">", 0))
738-
Expect(totalResources.DiskMB).To(BeNumerically("<=", math.MaxInt32))
739-
})
758+
It("returns the resources it was configured with, with live disk capacity", func() {
759+
result, err := depotClient.TotalResources(logger)
760+
Expect(err).NotTo(HaveOccurred())
761+
Expect(result.MemoryMB).To(Equal(resources.MemoryMB))
762+
Expect(result.Containers).To(Equal(resources.Containers))
763+
Expect(result.DiskMB).NotTo(Equal(math.MaxInt32))
764+
Expect(result.DiskMB).To(BeNumerically(">", 0))
740765
})
741766
})
742767
})
Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
//go:build !windows
2-
// +build !windows
32

43
package depot
54

65
import "syscall"
76

8-
func getDiskMB(diskPath string, fallback int) int {
9-
if diskPath == "" {
10-
return fallback
11-
}
7+
func liveDiskMB(path string) (int, bool) {
128
var stat syscall.Statfs_t
13-
if err := syscall.Statfs(diskPath, &stat); err == nil {
14-
return int(int64(stat.Bavail) * int64(stat.Bsize) / (1024 * 1024))
9+
if err := syscall.Statfs(path, &stat); err != nil {
10+
return 0, false
1511
}
16-
return fallback
12+
return int(int64(stat.Bavail) * int64(stat.Bsize) / (1024 * 1024)), true
1713
}

0 commit comments

Comments
 (0)