From 97961a6ad1dfc3012b97eb73505b3f869ec8adeb Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Fri, 23 Jun 2023 12:53:54 +0200 Subject: [PATCH] layer tree: be more resilient Make operating on the layer tree more resilient towards parallel image removals by checking for unknown-image errors. This partially fixes below linked BZ. At the time of writing, I do not have a reliable easy (and short running) reproducer. Hence, I suggest to merge this change without tests and rely on either Podman CI (which doesn't have a reliable test yet either) and the QE team (will be informed). BZ: bugzilla.redhat.com/show_bug.cgi?id=2216700 Signed-off-by: Valentin Rothberg --- libimage/layer_tree.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libimage/layer_tree.go b/libimage/layer_tree.go index a7d2f8c58..c9de814a7 100644 --- a/libimage/layer_tree.go +++ b/libimage/layer_tree.go @@ -2,6 +2,7 @@ package libimage import ( "context" + "errors" "github.com/containers/storage" ociv1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -31,6 +32,9 @@ func (t *layerTree) node(layerID string) *layerNode { } // toOCI returns an OCI image for the specified image. +// +// WARNING: callers are responsible for handling cases where the target image +// has been removed and need to check for `storage.ErrImageUnknown`. func (t *layerTree) toOCI(ctx context.Context, i *Image) (*ociv1.Image, error) { var err error oci, exists := t.ociCache[i.ID()] @@ -155,6 +159,9 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I parentID := parent.ID() parentOCI, err := t.toOCI(ctx, parent) if err != nil { + if errors.Is(err, storage.ErrImageUnknown) { + return nil, nil + } return nil, err } @@ -165,6 +172,9 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I } childOCI, err := t.toOCI(ctx, child) if err != nil { + if errors.Is(err, storage.ErrImageUnknown) { + return false, nil + } return false, err } // History check. @@ -255,6 +265,9 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { childID := child.ID() childOCI, err := t.toOCI(ctx, child) if err != nil { + if errors.Is(err, storage.ErrImageUnknown) { + return nil, nil + } return nil, err } @@ -268,6 +281,9 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { } emptyOCI, err := t.toOCI(ctx, empty) if err != nil { + if errors.Is(err, storage.ErrImageUnknown) { + return nil, nil + } return nil, err } // History check. @@ -300,6 +316,9 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { } parentOCI, err := t.toOCI(ctx, parent) if err != nil { + if errors.Is(err, storage.ErrImageUnknown) { + return nil, nil + } return nil, err } // History check.