Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions common/libimage/corrupted_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,29 @@ func TestCorruptedLayers(t *testing.T) {
_, err = image.Inspect(ctx, nil)
require.NoError(t, err, "inspecting repaired image should work")
}

func TestDiskUsageRemovedImage(t *testing.T) {
// An image can be removed by a parallel process between DiskUsage's
// listing and the per-image walk. The stale handle then fails with
// "image not known", which is not a corruption. DiskUsage skips it;
// that requires the wrapped error to keep its type.
runtime := testNewRuntime(t)
ctx := context.Background()
pullOptions := &PullOptions{}
pullOptions.Writer = os.Stdout

pulledImages, err := runtime.Pull(ctx, "quay.io/libpod/alpine_nginx:latest", config.PullPolicyAlways, pullOptions)
require.NoError(t, err)
require.Len(t, pulledImages, 1)
staleImage := pulledImages[0]

_, errs := runtime.store.DeleteImage(staleImage.ID(), true)
require.Nil(t, errs, "deleting the image from the store")

err = staleImage.isCorrupted(ctx, "")
require.Error(t, err, "stale handle reports an error")
require.ErrorIs(t, err, storage.ErrImageUnknown, "the wrapped error keeps its type")

_, _, err = runtime.DiskUsage(ctx)
require.NoError(t, err, "disk usage does not fail because of a removed image")
}
7 changes: 7 additions & 0 deletions common/libimage/disk_usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package libimage

import (
"context"
"errors"
"time"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -73,6 +74,12 @@ func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, int64, error
for _, image := range images {
usages, err := diskUsageForImage(ctx, image, layerMap, layerCount, &totalSize)
if err != nil {
// The image can be removed by a parallel process between the
// listing above and reading it here. That is not a corruption,
// skip it instead of failing the whole disk usage.
if errors.Is(err, storage.ErrImageUnknown) {
continue
}
return nil, -1, err
}
allUsages = append(allUsages, usages...)
Expand Down
2 changes: 1 addition & 1 deletion common/libimage/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (i *Image) isCorrupted(ctx context.Context, name string) error {
if name == "" {
name = i.ID()[:12]
}
return fmt.Errorf("Image %s exists in local storage but may be corrupted (remove the image to resolve the issue): %v", name, err)
return fmt.Errorf("Image %s exists in local storage but may be corrupted (remove the image to resolve the issue): %w", name, err)
Comment thread
vtushar06 marked this conversation as resolved.
}
return img.Close()
}
Expand Down
Loading