Skip to content

Commit

Permalink
Merge pull request #1194 from vrothberg/disk-usage
Browse files Browse the repository at this point in the history
DiskUsage: return total images size
  • Loading branch information
openshift-merge-robot authored Oct 18, 2022
2 parents 98295c0 + baebe0e commit 95c452e
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 24 deletions.
6 changes: 2 additions & 4 deletions libimage/corrupted_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,8 @@ func TestCorruptedLayers(t *testing.T) {
require.True(t, exists, "healthy image exists")

// Disk usage works.
_, err = runtime.DiskUsage(ctx)
_, _, err = runtime.DiskUsage(ctx)
require.NoError(t, err, "disk usage works on healthy image")
_, err = runtime.LayersDiskUsage(ctx)
require.NoError(t, err, "layers disk usage works on healthy image")

// Now remove one layer from the layers.json index in the storage. The
// image will still be listed in the container storage but attempting
Expand Down Expand Up @@ -77,7 +75,7 @@ func TestCorruptedLayers(t *testing.T) {
require.False(t, exists, "corrupted image should not be marked to exist")

// Disk usage does not work.
_, err = runtime.DiskUsage(ctx)
_, _, err = runtime.DiskUsage(ctx)
require.Error(t, err, "disk usage does not work on corrupted image")
require.Contains(t, err.Error(), "exists in local storage but may be corrupted", "disk usage reports corrupted image")

Expand Down
50 changes: 30 additions & 20 deletions libimage/disk_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,6 @@ import (
"time"
)

// LayersDiskUsage returns the sum of the size of all layers in the current store.
func (r *Runtime) LayersDiskUsage(ctx context.Context) (int64, error) {
layers, err := r.store.Layers()
if err != nil {
return -1, err
}

var size int64
for _, l := range layers {
size += l.UncompressedSize
}

return size, nil
}

// ImageDiskUsage reports the total size of an image. That is the size
type ImageDiskUsage struct {
// Number of containers using the image.
Expand All @@ -43,26 +28,51 @@ type ImageDiskUsage struct {
// DiskUsage calculates the disk usage for each image in the local containers
// storage. Note that a single image may yield multiple usage reports, one for
// each repository tag.
func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, error) {
func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, int64, error) {
layerTree, err := r.layerTree()
if err != nil {
return nil, err
return nil, -1, err
}

images, err := r.ListImages(ctx, nil, nil)
if err != nil {
return nil, err
return nil, -1, err
}

var totalSize int64
visitedImages := make(map[string]bool)
visistedLayers := make(map[string]bool)

var allUsages []ImageDiskUsage
for _, image := range images {
usages, err := diskUsageForImage(ctx, image, layerTree)
if err != nil {
return nil, err
return nil, -1, err
}
allUsages = append(allUsages, usages...)

if _, ok := visitedImages[image.ID()]; ok {
// Do not count an image twice
continue
}
visitedImages[image.ID()] = true

size, err := image.Size()
if err != nil {
return nil, -1, err
}
for _, layer := range layerTree.layersOf(image) {
if _, ok := visistedLayers[layer.ID]; ok {
// Do not count a layer twice, so remove its
// size from the image size.
size -= layer.UncompressedSize
continue
}
visistedLayers[layer.ID] = true
}
totalSize += size
}
return allUsages, err
return allUsages, totalSize, err
}

// diskUsageForImage returns the disk-usage baseistics for the specified image.
Expand Down
1 change: 1 addition & 0 deletions libimage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,7 @@ func (i *Image) Unmount(force bool) error {

// Size computes the size of the image layers and associated data.
func (i *Image) Size() (int64, error) {
// TODO: cache the result to optimize performance of subsequent calls
return i.runtime.store.ImageSize(i.ID())
}

Expand Down
11 changes: 11 additions & 0 deletions libimage/layer_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,17 @@ func (r *Runtime) layerTree() (*layerTree, error) {
return &tree, nil
}

// layersOf returns all storage layers of the specified image.
func (t *layerTree) layersOf(image *Image) []*storage.Layer {
var layers []*storage.Layer
node := t.node(image.TopLayer())
for node != nil {
layers = append(layers, node.layer)
node = node.parent
}
return layers
}

// children returns the child images of parent. Child images are images with
// either the same top layer as parent or parent being the true parent layer.
// Furthermore, the history of the parent and child images must match with the
Expand Down

0 comments on commit 95c452e

Please sign in to comment.