docker/patch/0052-docker-Lock-the-RWLayer-while-committing-expo.patch

195 lines
6.0 KiB
Diff
Raw Permalink Normal View History

2019-09-30 10:37:25 -04:00
From 568c9501d56ccff1806253f9e2289fdd5c002231 Mon Sep 17 00:00:00 2001
From: zhangyu235 <zhangyu235@huawei.com>
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 <pengyuanhong@huawei.com>
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
---
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