From 2b41c414a53011ce005890ff9310bfa5c71fbfbc Mon Sep 17 00:00:00 2001 From: zhangsong34 Date: Fri, 18 Jan 2019 17:39:32 +0800 Subject: [PATCH 108/111] docker: Fix can't run image while the image is not in `docker images` reason:When the layers of image has been damaged, daemon restart fail to load image, it cause docker can't run the image with unrecognized image ID error. Change-Id: I1cecc0dd602cd5a60006ba5c3e6060bd4071fb8e Signed-off-by: PengFei Yang Signed-off-by: zhangsong34 --- components/engine/daemon/daemon.go | 28 +++++++++++++++++++++++ components/engine/plugin/backend_linux.go | 4 ++++ components/engine/reference/store.go | 14 ++++++++++++ 3 files changed, 46 insertions(+) diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go index c96e28d88d..7716964304 100644 --- a/components/engine/daemon/daemon.go +++ b/components/engine/daemon/daemon.go @@ -1028,6 +1028,34 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S return nil, err } + // delete reference of image not nornamlly loaded to imageStore + for _, imageID := range rs.List() { + if img, err := imageStore.Get(image.ID(imageID)); err == nil { + isExist := false + if chainID := img.RootFS.ChainID(); chainID != "" { + l, err := layerStores[runtime.GOOS].Get(chainID) + if err == nil { + layer.ReleaseAndLog(layerStores[runtime.GOOS], l) + isExist = true + } + } else { + isExist = true + } + // If the image not exist locally, delete its reference + if !isExist { + for _, ref := range rs.References(imageID) { + isDelete, err := rs.Delete(ref) + if isDelete { + logrus.Warnf("Delete reference %s for image id %s from reference store", ref.String(), imageID) + } + if err != nil { + logrus.Warnf("Faild to delete reference %s for image id %s: %v", ref.String(), imageID, err) + } + } + } + } + } + // No content-addressability migration on Windows as it never supported pre-CA if runtime.GOOS != "windows" { migrationStart := time.Now() diff --git a/components/engine/plugin/backend_linux.go b/components/engine/plugin/backend_linux.go index 044e14b0cb..e5d3be15ee 100644 --- a/components/engine/plugin/backend_linux.go +++ b/components/engine/plugin/backend_linux.go @@ -490,6 +490,10 @@ func (r *pluginReference) References(id digest.Digest) []reference.Named { return []reference.Named{r.name} } +func (r *pluginReference) List() []digest.Digest { + return []digest.Digest{} +} + func (r *pluginReference) ReferencesByName(ref reference.Named) []refstore.Association { return []refstore.Association{ { diff --git a/components/engine/reference/store.go b/components/engine/reference/store.go index e54f772b5e..0df11271a7 100644 --- a/components/engine/reference/store.go +++ b/components/engine/reference/store.go @@ -34,6 +34,7 @@ type Store interface { AddDigest(ref reference.Canonical, id digest.Digest, force bool) error Delete(ref reference.Named) (bool, error) Get(ref reference.Named) (digest.Digest, error) + List() []digest.Digest } type store struct { @@ -274,6 +275,19 @@ func (store *store) References(id digest.Digest) []reference.Named { return references } +// List retrieves list of image ID, return nil if no image +func (store *store) List() []digest.Digest { + store.mu.RLock() + defer store.mu.RUnlock() + + var ids []digest.Digest + for id, _ := range store.referencesByIDCache { + ids = append(ids, id) + } + + return ids +} + // ReferencesByName returns the references for a given repository name. // If there are no references known for this repository name, // ReferencesByName returns nil. -- 2.17.1