mirror of https://github.com/docker/docs.git
Remove ref counting from layer store
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
5b6b8df0c1
commit
e19499710e
|
@ -502,15 +502,9 @@ func (ls *layerStore) ReinitRWLayer(l RWLayer) error {
|
||||||
ls.mountL.Lock()
|
ls.mountL.Lock()
|
||||||
defer ls.mountL.Unlock()
|
defer ls.mountL.Unlock()
|
||||||
|
|
||||||
m, ok := ls.mounts[l.Name()]
|
if _, ok := ls.mounts[l.Name()]; !ok {
|
||||||
if !ok {
|
|
||||||
return ErrMountDoesNotExist
|
return ErrMountDoesNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.incActivityCount(l); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -400,14 +400,11 @@ func TestStoreRestore(t *testing.T) {
|
||||||
if err := ioutil.WriteFile(filepath.Join(path, "testfile.txt"), []byte("nothing here"), 0644); err != nil {
|
if err := ioutil.WriteFile(filepath.Join(path, "testfile.txt"), []byte("nothing here"), 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
assertActivityCount(t, m, 1)
|
|
||||||
|
|
||||||
if err := m.Unmount(); err != nil {
|
if err := m.Unmount(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertActivityCount(t, m, 0)
|
|
||||||
|
|
||||||
ls2, err := NewStoreFromGraphDriver(ls.(*layerStore).store, ls.(*layerStore).driver)
|
ls2, err := NewStoreFromGraphDriver(ls.(*layerStore).store, ls.(*layerStore).driver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -438,20 +435,15 @@ func TestStoreRestore(t *testing.T) {
|
||||||
t.Fatalf("Unexpected path %s, expected %s", mountPath, path)
|
t.Fatalf("Unexpected path %s, expected %s", mountPath, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertActivityCount(t, m2, 1)
|
|
||||||
|
|
||||||
if mountPath, err := m2.Mount(""); err != nil {
|
if mountPath, err := m2.Mount(""); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if path != mountPath {
|
} else if path != mountPath {
|
||||||
t.Fatalf("Unexpected path %s, expected %s", mountPath, path)
|
t.Fatalf("Unexpected path %s, expected %s", mountPath, path)
|
||||||
}
|
}
|
||||||
assertActivityCount(t, m2, 2)
|
|
||||||
if err := m2.Unmount(); err != nil {
|
if err := m2.Unmount(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertActivityCount(t, m2, 1)
|
|
||||||
|
|
||||||
b, err := ioutil.ReadFile(filepath.Join(path, "testfile.txt"))
|
b, err := ioutil.ReadFile(filepath.Join(path, "testfile.txt"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -464,8 +456,6 @@ func TestStoreRestore(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertActivityCount(t, m2, 0)
|
|
||||||
|
|
||||||
if metadata, err := ls2.ReleaseRWLayer(m2); err != nil {
|
if metadata, err := ls2.ReleaseRWLayer(m2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if len(metadata) != 0 {
|
} else if len(metadata) != 0 {
|
||||||
|
@ -674,13 +664,6 @@ func assertReferences(t *testing.T, references ...Layer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertActivityCount(t *testing.T, l RWLayer, expected int) {
|
|
||||||
rl := l.(*referencedRWLayer)
|
|
||||||
if rl.activityCount != expected {
|
|
||||||
t.Fatalf("Unexpected activity count %d, expected %d", rl.activityCount, expected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegisterExistingLayer(t *testing.T) {
|
func TestRegisterExistingLayer(t *testing.T) {
|
||||||
ls, _, cleanup := newTestStore(t)
|
ls, _, cleanup := newTestStore(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
|
@ -380,8 +380,6 @@ func TestMountMigration(t *testing.T) {
|
||||||
Kind: archive.ChangeAdd,
|
Kind: archive.ChangeAdd,
|
||||||
})
|
})
|
||||||
|
|
||||||
assertActivityCount(t, rwLayer1, 1)
|
|
||||||
|
|
||||||
if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), "", nil, nil); err == nil {
|
if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), "", nil, nil); err == nil {
|
||||||
t.Fatal("Expected error creating mount with same name")
|
t.Fatal("Expected error creating mount with same name")
|
||||||
} else if err != ErrMountNameConflict {
|
} else if err != ErrMountNameConflict {
|
||||||
|
@ -401,16 +399,10 @@ func TestMountMigration(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertActivityCount(t, rwLayer2, 1)
|
|
||||||
assertActivityCount(t, rwLayer1, 1)
|
|
||||||
|
|
||||||
if _, err := rwLayer2.Mount(""); err != nil {
|
if _, err := rwLayer2.Mount(""); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertActivityCount(t, rwLayer2, 2)
|
|
||||||
assertActivityCount(t, rwLayer1, 1)
|
|
||||||
|
|
||||||
if metadata, err := ls.Release(layer1); err != nil {
|
if metadata, err := ls.Release(layer1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if len(metadata) > 0 {
|
} else if len(metadata) > 0 {
|
||||||
|
@ -420,8 +412,6 @@ func TestMountMigration(t *testing.T) {
|
||||||
if err := rwLayer1.Unmount(); err != nil {
|
if err := rwLayer1.Unmount(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
assertActivityCount(t, rwLayer2, 2)
|
|
||||||
assertActivityCount(t, rwLayer1, 0)
|
|
||||||
|
|
||||||
if _, err := ls.ReleaseRWLayer(rwLayer1); err != nil {
|
if _, err := ls.ReleaseRWLayer(rwLayer1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -430,9 +420,6 @@ func TestMountMigration(t *testing.T) {
|
||||||
if err := rwLayer2.Unmount(); err != nil {
|
if err := rwLayer2.Unmount(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := ls.ReleaseRWLayer(rwLayer2); err == nil {
|
|
||||||
t.Fatal("Expected error deleting active mount")
|
|
||||||
}
|
|
||||||
if err := rwLayer2.Unmount(); err != nil {
|
if err := rwLayer2.Unmount(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package layer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/archive"
|
"github.com/docker/docker/pkg/archive"
|
||||||
)
|
)
|
||||||
|
@ -83,106 +82,30 @@ func (ml *mountedLayer) hasReferences() bool {
|
||||||
return len(ml.references) > 0
|
return len(ml.references) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ml *mountedLayer) incActivityCount(ref RWLayer) error {
|
|
||||||
rl, ok := ml.references[ref]
|
|
||||||
if !ok {
|
|
||||||
return ErrLayerNotRetained
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rl.acquire(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ml *mountedLayer) deleteReference(ref RWLayer) error {
|
func (ml *mountedLayer) deleteReference(ref RWLayer) error {
|
||||||
rl, ok := ml.references[ref]
|
if _, ok := ml.references[ref]; !ok {
|
||||||
if !ok {
|
|
||||||
return ErrLayerNotRetained
|
return ErrLayerNotRetained
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rl.release(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
delete(ml.references, ref)
|
delete(ml.references, ref)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ml *mountedLayer) retakeReference(r RWLayer) {
|
func (ml *mountedLayer) retakeReference(r RWLayer) {
|
||||||
if ref, ok := r.(*referencedRWLayer); ok {
|
if ref, ok := r.(*referencedRWLayer); ok {
|
||||||
ref.activityCount = 0
|
|
||||||
ml.references[ref] = ref
|
ml.references[ref] = ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type referencedRWLayer struct {
|
type referencedRWLayer struct {
|
||||||
*mountedLayer
|
*mountedLayer
|
||||||
|
|
||||||
activityL sync.Mutex
|
|
||||||
activityCount int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rl *referencedRWLayer) acquire() error {
|
|
||||||
rl.activityL.Lock()
|
|
||||||
defer rl.activityL.Unlock()
|
|
||||||
|
|
||||||
rl.activityCount++
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rl *referencedRWLayer) release() error {
|
|
||||||
rl.activityL.Lock()
|
|
||||||
defer rl.activityL.Unlock()
|
|
||||||
|
|
||||||
if rl.activityCount > 0 {
|
|
||||||
return ErrActiveMount
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.activityCount = -1
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *referencedRWLayer) Mount(mountLabel string) (string, error) {
|
func (rl *referencedRWLayer) Mount(mountLabel string) (string, error) {
|
||||||
rl.activityL.Lock()
|
return rl.mountedLayer.Mount(mountLabel)
|
||||||
defer rl.activityL.Unlock()
|
|
||||||
|
|
||||||
if rl.activityCount == -1 {
|
|
||||||
return "", ErrLayerNotRetained
|
|
||||||
}
|
|
||||||
|
|
||||||
if rl.activityCount > 0 {
|
|
||||||
rl.activityCount++
|
|
||||||
return rl.path, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err := rl.mountedLayer.Mount(mountLabel)
|
|
||||||
if err == nil {
|
|
||||||
rl.activityCount++
|
|
||||||
rl.path = m
|
|
||||||
}
|
|
||||||
return m, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmount decrements the activity count and unmounts the underlying layer
|
// Unmount decrements the activity count and unmounts the underlying layer
|
||||||
// Callers should only call `Unmount` once per call to `Mount`, even on error.
|
// Callers should only call `Unmount` once per call to `Mount`, even on error.
|
||||||
func (rl *referencedRWLayer) Unmount() error {
|
func (rl *referencedRWLayer) Unmount() error {
|
||||||
rl.activityL.Lock()
|
|
||||||
defer rl.activityL.Unlock()
|
|
||||||
|
|
||||||
if rl.activityCount == 0 {
|
|
||||||
return ErrNotMounted
|
|
||||||
}
|
|
||||||
if rl.activityCount == -1 {
|
|
||||||
return ErrLayerNotRetained
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.activityCount--
|
|
||||||
if rl.activityCount > 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return rl.mountedLayer.Unmount()
|
return rl.mountedLayer.Unmount()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue