Fix reclaimable image disk usage calculation for in-use images#51778
Fix reclaimable image disk usage calculation for in-use images#51778thaJeztah merged 1 commit intomoby:masterfrom
Conversation
63e1ad4 to
9dc6860
Compare
|
Opening up early to get some eyes on it + run the full test suite. I need a bit more time to write some integration tests for the daemon. Also I have this annoying issue where because of the swap from reclaimable = total - inUse to reclaimable = 0 + unused. The df output is showing 99% due to the minor delta. My hunch is it might be containerd backend metadata diff. Need to look into it some more though. |
There was a problem hiding this comment.
Pull request overview
This PR fixes the reclaimable image disk usage calculation for in-use images by changing from a subtraction-based approach to an additive approach. Previously, the code initialized Reclaimable to the total size and subtracted active images, which could lead to incorrect calculations when images had invalid size values (-1).
- Changed calculation logic to build up reclaimable space by adding unused images instead of subtracting used images
- Applied the fix to both
daemon/disk_usage.goandclient/system_disk_usage.go - Added comprehensive test coverage for various image disk usage scenarios
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| daemon/disk_usage.go | Updated to calculate reclaimable space by accumulating unused images instead of subtracting active images from total |
| client/system_disk_usage.go | Applied the same calculation fix to the legacy API conversion function |
| client/system_disk_usage_test.go | Added new test suite covering no images, images without containers, images with containers, and images with shared size scenarios |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
0977c7f to
c1ab10d
Compare
|
Through some debug logs, I found the delta was 6688 bytes for the |
7fff3bb to
bcb1c1a
Compare
| // Also include the size of image index if it was included | ||
| if i.Descriptor != nil && i.Descriptor.MediaType == ocispec.MediaTypeImageIndex { | ||
| du.Reclaimable += i.Descriptor.Size |
There was a problem hiding this comment.
Through my testing, I found the reclaimable size is off if the image contains an OCI image index. Docker schema v2 images; however, do not need to include the top level descriptor size. Open to thoughts if there is a better option to compute this value.
There was a problem hiding this comment.
Looking at the code, shouldn't the descriptor size also be added to TotalSize ? Before this change, we'd start with both Reclaimable and TotalSize to be set to totalSize (calculated through daemon.imageService.ImageDiskUsage(ctx)). After this change, we correct the Reclaimable size, but don't adjust TotalSize.
Wondering if the actual issue is that daemon.imageService.ImageDiskUsage(ctx) doesn't include the manifest size, or does that function not have access to the descriptors?
There was a problem hiding this comment.
The containerd image service is computing the total size as the sum of all layers and the size of any content for the image including the image index. (quick-link
moby/daemon/containerd/service.go
Lines 154 to 167 in fba74ac
Perhaps a better fix would be to have the image summary Size field include the size of additional content including the image index.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
a9e9dc1 to
73b0c3d
Compare
73b0c3d to
5aa5866
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| name: "multiplatform image with an image index", | ||
| mockResponse: &legacyDiskUsage{ | ||
| LayersSize: 4608, | ||
| Images: []image.Summary{ | ||
| {ID: "image1", Size: 4096, SharedSize: 0, Containers: 0, Descriptor: &ocispec.Descriptor{MediaType: ocispec.MediaTypeImageIndex, Size: 512}}, | ||
| }, | ||
| }, | ||
| expectedActiveCount: 0, | ||
| expectedTotalCount: 1, | ||
| expectedReclaimable: 4608, // (4096 - 0) + 512 | ||
| expectedTotalSize: 4608, | ||
| }, | ||
| { | ||
| name: "multiplatform image with a Docker distribution manifest", | ||
| mockResponse: &legacyDiskUsage{ | ||
| LayersSize: 4096, | ||
| Images: []image.Summary{ | ||
| {ID: "image1", Size: 4096, SharedSize: 0, Containers: 0, Descriptor: &ocispec.Descriptor{MediaType: "application/vnd.docker.distribution.manifest.v2+json", Size: 427}}, | ||
| }, | ||
| }, | ||
| expectedActiveCount: 0, | ||
| expectedTotalCount: 1, | ||
| expectedReclaimable: 4096, // (4096 - 0) | ||
| expectedTotalSize: 4096, | ||
| }, |
5aa5866 to
3072f1e
Compare
This change reworks to build up the reclaimable image disk uage instead of setting it to total size and subtracting active images. This change also includes the image index size as reclaimable if it is included with the image summary. Signed-off-by: Austin Vazquez <[email protected]>
3072f1e to
46dba49
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| du.Reclaimable -= i.Size - i.SharedSize | ||
| if i.Containers > 0 { | ||
| du.ActiveCount++ | ||
| } else if i.Size != -1 && i.SharedSize != -1 { |
There was a problem hiding this comment.
image.Summary.Containers uses -1 as a sentinel for “not set” (see image list code paths). With the current if i.Containers > 0 { … } else if i.Size != -1 … { du.Reclaimable += … }, images with Containers == -1 will be treated as unused and counted as reclaimable, which can reintroduce “in-use images shown as reclaimable” when container-count is unavailable.
Consider tightening the reclaimable branch to only run when i.Containers == 0 (and optionally skipping reclaimable calculation when i.Containers < 0).
| } else if i.Size != -1 && i.SharedSize != -1 { | |
| } else if i.Containers == 0 && i.Size != -1 && i.SharedSize != -1 { |
| } else if i.Size != -1 && i.SharedSize != -1 { | ||
| // Only count reclaimable size if we have size information |
There was a problem hiding this comment.
image.Summary.Containers can be -1 to indicate “not set”. In that case, the current if i.Containers > 0 { … } else if i.Size != -1 … { idu.Reclaimable += … } will treat Containers == -1 as unused and count it as reclaimable.
To avoid incorrect reclaimable reporting when container-count is unknown, change the reclaimable branch to require i.Containers == 0 (and optionally skip reclaimable calculation for i.Containers < 0).
| } else if i.Size != -1 && i.SharedSize != -1 { | |
| // Only count reclaimable size if we have size information | |
| } else if i.Containers == 0 && i.Size != -1 && i.SharedSize != -1 { | |
| // Only count reclaimable size if we have size information and container-count is known to be zero |
|
LOL; told ya! Once it starts reviewing it will continue providing comments; at least one new (nit-pick) for every review cycle 😆😆 |
thaJeztah
left a comment
There was a problem hiding this comment.
LGTM, we can look at follow-ups for the CoPilot comments
- What I did
This change reworks to build up the reclaimable image disk usage instead of setting it to total size and subtracting active images.
- How I did it
- How to verify it
- Human readable description for the release notes
- A picture of a cute animal (not mandatory but encouraged)