From 568c9501d56ccff1806253f9e2289fdd5c002231 Mon Sep 17 00:00:00 2001 From: zhangyu235 Date: Thu, 17 Jan 2019 20:03:14 +0800 Subject: [PATCH 052/111] docker: Lock the RWLayer while committing/exporting reason:Add a rw mutex to `mountLayer/roLayer/emptyLayer` and introduce new methods `RLockRWLayer()` and `RUnlockRWLayer()` to `RWLayer`. Now the rw layer of the container would be locked to block removal of that layer. Cherry-pick from docker 1.11.2: - 2923a77c Lock the RWLayer while committing/exporting Change-Id: I11d6dcb60a23fe3516cebaed36d19aabaa863769 Signed-off-by: Yuanhong Peng Signed-off-by: zhangyu235 --- components/engine/daemon/commit.go | 2 ++ components/engine/daemon/export.go | 2 ++ components/engine/layer/empty.go | 13 ++++++++++++- components/engine/layer/layer.go | 7 +++++++ components/engine/layer/layer_store.go | 2 ++ components/engine/layer/mounted_layer.go | 10 ++++++++++ components/engine/layer/ro_layer.go | 10 ++++++++++ 7 files changed, 45 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/commit.go b/components/engine/daemon/commit.go index 0f6f440514..fc7d2782ef 100644 --- a/components/engine/daemon/commit.go +++ b/components/engine/daemon/commit.go @@ -155,6 +155,8 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma return "", err } + container.RWLayer.RLockRWLayer() + defer container.RWLayer.RUnlockRWLayer() id, err := daemon.imageService.CommitImage(backend.CommitConfig{ Author: c.Author, Comment: c.Comment, diff --git a/components/engine/daemon/export.go b/components/engine/daemon/export.go index 27bc35967d..ebd2d75f40 100644 --- a/components/engine/daemon/export.go +++ b/components/engine/daemon/export.go @@ -34,6 +34,8 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error { return errdefs.Conflict(err) } + container.RWLayer.RLockRWLayer() + defer container.RWLayer.RUnlockRWLayer() data, err := daemon.containerExport(container) if err != nil { return fmt.Errorf("Error exporting container %s: %v", name, err) diff --git a/components/engine/layer/empty.go b/components/engine/layer/empty.go index c81c702140..16a49a7abd 100644 --- a/components/engine/layer/empty.go +++ b/components/engine/layer/empty.go @@ -6,13 +6,16 @@ import ( "fmt" "io" "io/ioutil" + "sync" ) // DigestSHA256EmptyTar is the canonical sha256 digest of empty tar file - // (1024 NULL bytes) const DigestSHA256EmptyTar = DiffID("sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef") -type emptyLayer struct{} +type emptyLayer struct { + sync.RWMutex +} // EmptyLayer is a layer that corresponds to empty tar. var EmptyLayer = &emptyLayer{} @@ -55,6 +58,14 @@ func (el *emptyLayer) Metadata() (map[string]string, error) { return make(map[string]string), nil } +func (el *emptyLayer) RLockRWLayer() { + el.RLock() +} + +func (el *emptyLayer) RUnlockRWLayer() { + el.RUnlock() +} + // IsEmpty returns true if the layer is an EmptyLayer func IsEmpty(diffID DiffID) bool { return diffID == DigestSHA256EmptyTar diff --git a/components/engine/layer/layer.go b/components/engine/layer/layer.go index cb13c98d0b..e35a13135b 100644 --- a/components/engine/layer/layer.go +++ b/components/engine/layer/layer.go @@ -145,6 +145,13 @@ type RWLayer interface { // Metadata returns the low level metadata for the mutable layer Metadata() (map[string]string, error) + + // RLockRWLayer locks the RWLayer to block unmounting/removal + // of that layer + RLockRWLayer() + + // RUnlockRWLayer unlocks the RWLayer + RUnlockRWLayer() } // Metadata holds information about a diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go index f22e9c666c..7c80a29645 100644 --- a/components/engine/layer/layer_store.go +++ b/components/engine/layer/layer_store.go @@ -666,6 +666,8 @@ func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) { return []Metadata{}, nil } + m.Lock() + defer m.Unlock() if err := m.deleteReference(l); err != nil { return nil, err } diff --git a/components/engine/layer/mounted_layer.go b/components/engine/layer/mounted_layer.go index d6858c662c..66711d6cf7 100644 --- a/components/engine/layer/mounted_layer.go +++ b/components/engine/layer/mounted_layer.go @@ -2,6 +2,7 @@ package layer // import "github.com/docker/docker/layer" import ( "io" + "sync" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/containerfs" @@ -16,6 +17,7 @@ type mountedLayer struct { layerStore *layerStore references map[RWLayer]*referencedRWLayer + sync.RWMutex } func (ml *mountedLayer) cacheParent() string { @@ -58,6 +60,14 @@ func (ml *mountedLayer) Metadata() (map[string]string, error) { return ml.layerStore.driver.GetMetadata(ml.mountID) } +func (ml *mountedLayer) RLockRWLayer() { + ml.RLock() +} + +func (ml *mountedLayer) RUnlockRWLayer() { + ml.RUnlock() +} + func (ml *mountedLayer) getReference() RWLayer { ref := &referencedRWLayer{ mountedLayer: ml, diff --git a/components/engine/layer/ro_layer.go b/components/engine/layer/ro_layer.go index 3555e8b027..59bcf17d18 100644 --- a/components/engine/layer/ro_layer.go +++ b/components/engine/layer/ro_layer.go @@ -3,6 +3,7 @@ package layer // import "github.com/docker/docker/layer" import ( "fmt" "io" + "sync" "github.com/docker/distribution" "github.com/opencontainers/go-digest" @@ -19,6 +20,7 @@ type roLayer struct { referenceCount int references map[Layer]struct{} + sync.RWMutex } // TarStream for roLayer guarantees that the data that is produced is the exact @@ -92,6 +94,14 @@ func (rl *roLayer) Metadata() (map[string]string, error) { return rl.layerStore.driver.GetMetadata(rl.cacheID) } +func (rl *roLayer) RLockRWLayer() { + rl.RLock() +} + +func (rl *roLayer) RUnlockRWLayer() { + rl.RUnlock() +} + type referencedCacheLayer struct { *roLayer } -- 2.17.1