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