Browse code

Refactor RWLayer to use referenced object instead of string

RWLayer will now have more operations and be protected through a referenced type rather than always looked up by string in the layer store.
Separates creation of RWLayer (write capture layer) from mounting of the layer.
This allows mount labels to be applied after creation and allowing RWLayer objects to have the same lifespan as a container without performance regressions from requiring mount.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)

Derek McGowan authored on 2015/12/17 07:13:50
Showing 18 changed files
... ...
@@ -145,7 +145,7 @@ func (daemon *Daemon) exportContainerRw(container *container.Container) (archive
145 145
 	}
146 146
 	return ioutils.NewReadCloserWrapper(archive, func() error {
147 147
 			archive.Close()
148
-			return daemon.layerStore.Unmount(container.ID)
148
+			return container.RWLayer.Unmount()
149 149
 		}),
150 150
 		nil
151 151
 }
... ...
@@ -98,7 +98,7 @@ func (daemon *Daemon) populateCommand(c *container.Container, env []string) erro
98 98
 		}
99 99
 	}
100 100
 
101
-	m, err := daemon.layerStore.Metadata(c.ID)
101
+	m, err := c.RWLayer.Metadata()
102 102
 	if err != nil {
103 103
 		return derr.ErrorCodeGetLayerMetadata.WithArgs(err)
104 104
 	}
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"github.com/docker/docker/container"
8 8
 	derr "github.com/docker/docker/errors"
9 9
 	"github.com/docker/docker/image"
10
+	"github.com/docker/docker/layer"
10 11
 	"github.com/docker/docker/pkg/idtools"
11 12
 	"github.com/docker/docker/pkg/stringid"
12 13
 	"github.com/docker/docker/volume"
... ...
@@ -95,6 +96,11 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig) (*container.Con
95 95
 		}
96 96
 	}()
97 97
 
98
+	// Set RWLayer for container after mount labels have been set
99
+	if err := daemon.setRWLayer(container); err != nil {
100
+		return nil, err
101
+	}
102
+
98 103
 	if err := daemon.createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil {
99 104
 		return nil, err
100 105
 	}
... ...
@@ -126,6 +132,24 @@ func (daemon *Daemon) generateSecurityOpt(ipcMode containertypes.IpcMode, pidMod
126 126
 	return nil, nil
127 127
 }
128 128
 
129
+func (daemon *Daemon) setRWLayer(container *container.Container) error {
130
+	var layerID layer.ChainID
131
+	if container.ImageID != "" {
132
+		img, err := daemon.imageStore.Get(container.ImageID)
133
+		if err != nil {
134
+			return err
135
+		}
136
+		layerID = img.RootFS.ChainID()
137
+	}
138
+	rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.MountLabel, daemon.setupInitLayer)
139
+	if err != nil {
140
+		return err
141
+	}
142
+	container.RWLayer = rwLayer
143
+
144
+	return nil
145
+}
146
+
129 147
 // VolumeCreate creates a volume with the specified name, driver, and opts
130 148
 // This is called directly from the remote API
131 149
 func (daemon *Daemon) VolumeCreate(name, driverName string, opts map[string]string) (*types.Volume, error) {
... ...
@@ -323,6 +323,13 @@ func (daemon *Daemon) restore() error {
323 323
 			continue
324 324
 		}
325 325
 
326
+		rwlayer, err := daemon.layerStore.GetRWLayer(container.ID)
327
+		if err != nil {
328
+			logrus.Errorf("Failed to load container mount %v: %v", id, err)
329
+			continue
330
+		}
331
+		container.RWLayer = rwlayer
332
+
326 333
 		// Ignore the container if it does not support the current driver being used by the graph
327 334
 		if (container.Driver == "" && currentDriver == "aufs") || container.Driver == currentDriver {
328 335
 			logrus.Debugf("Loaded container %v", container.ID)
... ...
@@ -961,19 +968,7 @@ func (daemon *Daemon) Shutdown() error {
961 961
 // Mount sets container.BaseFS
962 962
 // (is it not set coming in? why is it unset?)
963 963
 func (daemon *Daemon) Mount(container *container.Container) error {
964
-	var layerID layer.ChainID
965
-	if container.ImageID != "" {
966
-		img, err := daemon.imageStore.Get(container.ImageID)
967
-		if err != nil {
968
-			return err
969
-		}
970
-		layerID = img.RootFS.ChainID()
971
-	}
972
-	rwlayer, err := daemon.layerStore.Mount(container.ID, layerID, container.GetMountLabel(), daemon.setupInitLayer)
973
-	if err != nil {
974
-		return err
975
-	}
976
-	dir, err := rwlayer.Path()
964
+	dir, err := container.RWLayer.Mount(container.GetMountLabel())
977 965
 	if err != nil {
978 966
 		return err
979 967
 	}
... ...
@@ -990,13 +985,12 @@ func (daemon *Daemon) Mount(container *container.Container) error {
990 990
 		}
991 991
 	}
992 992
 	container.BaseFS = dir // TODO: combine these fields
993
-	container.RWLayer = rwlayer
994 993
 	return nil
995 994
 }
996 995
 
997 996
 // Unmount unsets the container base filesystem
998 997
 func (daemon *Daemon) Unmount(container *container.Container) {
999
-	if err := daemon.layerStore.Unmount(container.ID); err != nil {
998
+	if err := container.RWLayer.Unmount(); err != nil {
1000 999
 		logrus.Errorf("Error unmounting container %s: %s", container.ID, err)
1001 1000
 	}
1002 1001
 }
... ...
@@ -1029,7 +1023,7 @@ func (daemon *Daemon) unsubscribeToContainerStats(c *container.Container, ch cha
1029 1029
 }
1030 1030
 
1031 1031
 func (daemon *Daemon) changes(container *container.Container) ([]archive.Change, error) {
1032
-	return daemon.layerStore.Changes(container.ID)
1032
+	return container.RWLayer.Changes()
1033 1033
 }
1034 1034
 
1035 1035
 // TagImage creates a tag in the repository reponame, pointing to the image named
... ...
@@ -130,7 +130,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
130 130
 		return derr.ErrorCodeRmFS.WithArgs(container.ID, err)
131 131
 	}
132 132
 
133
-	metadata, err := daemon.layerStore.DeleteMount(container.ID)
133
+	metadata, err := daemon.layerStore.ReleaseRWLayer(container.RWLayer)
134 134
 	layer.LogReleaseMetadata(metadata)
135 135
 	if err != nil && err != layer.ErrMountDoesNotExist {
136 136
 		return derr.ErrorCodeRmDriverFS.WithArgs(daemon.driver, container.ID, err)
... ...
@@ -163,7 +163,7 @@ func (daemon *Daemon) getInspectData(container *container.Container, size bool)
163 163
 
164 164
 	contJSONBase.GraphDriver.Name = container.Driver
165 165
 
166
-	graphDriverData, err := daemon.layerStore.Metadata(container.ID)
166
+	graphDriverData, err := container.RWLayer.Metadata()
167 167
 	if err != nil {
168 168
 		return nil, err
169 169
 	}
... ...
@@ -12,7 +12,6 @@ import (
12 12
 	"github.com/docker/distribution/digest"
13 13
 	"github.com/docker/docker/image"
14 14
 	"github.com/docker/docker/layer"
15
-	"github.com/docker/docker/pkg/archive"
16 15
 	"github.com/docker/docker/pkg/progress"
17 16
 	"golang.org/x/net/context"
18 17
 )
... ...
@@ -115,25 +114,18 @@ func (ls *mockLayerStore) Get(chainID layer.ChainID) (layer.Layer, error) {
115 115
 func (ls *mockLayerStore) Release(l layer.Layer) ([]layer.Metadata, error) {
116 116
 	return []layer.Metadata{}, nil
117 117
 }
118
-
119
-func (ls *mockLayerStore) Mount(id string, parent layer.ChainID, label string, init layer.MountInit) (layer.RWLayer, error) {
118
+func (ls *mockLayerStore) CreateRWLayer(string, layer.ChainID, string, layer.MountInit) (layer.RWLayer, error) {
120 119
 	return nil, errors.New("not implemented")
121 120
 }
122 121
 
123
-func (ls *mockLayerStore) Unmount(id string) error {
124
-	return errors.New("not implemented")
125
-}
126
-
127
-func (ls *mockLayerStore) DeleteMount(id string) ([]layer.Metadata, error) {
122
+func (ls *mockLayerStore) GetRWLayer(string) (layer.RWLayer, error) {
128 123
 	return nil, errors.New("not implemented")
129
-}
130 124
 
131
-func (ls *mockLayerStore) Changes(id string) ([]archive.Change, error) {
132
-	return nil, errors.New("not implemented")
133 125
 }
134 126
 
135
-func (ls *mockLayerStore) Metadata(id string) (map[string]string, error) {
127
+func (ls *mockLayerStore) ReleaseRWLayer(layer.RWLayer) ([]layer.Metadata, error) {
136 128
 	return nil, errors.New("not implemented")
129
+
137 130
 }
138 131
 
139 132
 type mockDownloadDescriptor struct {
... ...
@@ -31,6 +31,11 @@ var (
31 31
 	// attempted on a mount layer which does not exist.
32 32
 	ErrMountDoesNotExist = errors.New("mount does not exist")
33 33
 
34
+	// ErrMountNameConflict is used when a mount is attempted
35
+	// to be created but there is already a mount with the name
36
+	// used for creation.
37
+	ErrMountNameConflict = errors.New("mount already exists with name")
38
+
34 39
 	// ErrActiveMount is used when an operation on a
35 40
 	// mount is attempted but the layer is still
36 41
 	// mounted and the operation cannot be performed.
... ...
@@ -103,18 +108,33 @@ type Layer interface {
103 103
 type RWLayer interface {
104 104
 	TarStreamer
105 105
 
106
-	// Path returns the filesystem path to the writable
107
-	// layer.
108
-	Path() (string, error)
106
+	// Name of mounted layer
107
+	Name() string
109 108
 
110 109
 	// Parent returns the layer which the writable
111 110
 	// layer was created from.
112 111
 	Parent() Layer
113 112
 
113
+	// Mount mounts the RWLayer and returns the filesystem path
114
+	// the to the writable layer.
115
+	Mount(mountLabel string) (string, error)
116
+
117
+	// Unmount unmounts the RWLayer. This should be called
118
+	// for every mount. If there are multiple mount calls
119
+	// this operation will only decrement the internal mount counter.
120
+	Unmount() error
121
+
114 122
 	// Size represents the size of the writable layer
115 123
 	// as calculated by the total size of the files
116 124
 	// changed in the mutable layer.
117 125
 	Size() (int64, error)
126
+
127
+	// Changes returns the set of changes for the mutable layer
128
+	// from the base layer.
129
+	Changes() ([]archive.Change, error)
130
+
131
+	// Metadata returns the low level metadata for the mutable layer
132
+	Metadata() (map[string]string, error)
118 133
 }
119 134
 
120 135
 // Metadata holds information about a
... ...
@@ -147,11 +167,9 @@ type Store interface {
147 147
 	Get(ChainID) (Layer, error)
148 148
 	Release(Layer) ([]Metadata, error)
149 149
 
150
-	Mount(id string, parent ChainID, label string, init MountInit) (RWLayer, error)
151
-	Unmount(id string) error
152
-	DeleteMount(id string) ([]Metadata, error)
153
-	Changes(id string) ([]archive.Change, error)
154
-	Metadata(id string) (map[string]string, error)
150
+	CreateRWLayer(id string, parent ChainID, mountLabel string, initFunc MountInit) (RWLayer, error)
151
+	GetRWLayer(id string) (RWLayer, error)
152
+	ReleaseRWLayer(RWLayer) ([]Metadata, error)
155 153
 }
156 154
 
157 155
 // MetadataTransaction represents functions for setting layer metadata
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"fmt"
6 6
 	"io"
7 7
 	"io/ioutil"
8
-	"runtime"
9 8
 	"sync"
10 9
 
11 10
 	"github.com/Sirupsen/logrus"
... ...
@@ -144,6 +143,7 @@ func (ls *layerStore) loadMount(mount string) error {
144 144
 		mountID:    mountID,
145 145
 		initID:     initID,
146 146
 		layerStore: ls,
147
+		references: map[RWLayer]*referencedRWLayer{},
147 148
 	}
148 149
 
149 150
 	if parent != "" {
... ...
@@ -382,78 +382,15 @@ func (ls *layerStore) Release(l Layer) ([]Metadata, error) {
382 382
 	return ls.releaseLayer(layer)
383 383
 }
384 384
 
385
-func (ls *layerStore) mount(m *mountedLayer, mountLabel string) error {
386
-	dir, err := ls.driver.Get(m.mountID, mountLabel)
387
-	if err != nil {
388
-		return err
389
-	}
390
-	m.path = dir
391
-	m.activityCount++
392
-
393
-	return nil
394
-}
395
-
396
-func (ls *layerStore) saveMount(mount *mountedLayer) error {
397
-	if err := ls.store.SetMountID(mount.name, mount.mountID); err != nil {
398
-		return err
399
-	}
400
-
401
-	if mount.initID != "" {
402
-		if err := ls.store.SetInitID(mount.name, mount.initID); err != nil {
403
-			return err
404
-		}
405
-	}
406
-
407
-	if mount.parent != nil {
408
-		if err := ls.store.SetMountParent(mount.name, mount.parent.chainID); err != nil {
409
-			return err
410
-		}
411
-	}
412
-
413
-	ls.mounts[mount.name] = mount
414
-
415
-	return nil
416
-}
417
-
418
-func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit) (string, error) {
419
-	// Use "<graph-id>-init" to maintain compatibility with graph drivers
420
-	// which are expecting this layer with this special name. If all
421
-	// graph drivers can be updated to not rely on knowing about this layer
422
-	// then the initID should be randomly generated.
423
-	initID := fmt.Sprintf("%s-init", graphID)
424
-
425
-	if err := ls.driver.Create(initID, parent, mountLabel); err != nil {
426
-		return "", err
427
-	}
428
-	p, err := ls.driver.Get(initID, "")
429
-	if err != nil {
430
-		return "", err
431
-	}
432
-
433
-	if err := initFunc(p); err != nil {
434
-		ls.driver.Put(initID)
435
-		return "", err
436
-	}
437
-
438
-	if err := ls.driver.Put(initID); err != nil {
439
-		return "", err
440
-	}
441
-
442
-	return initID, nil
443
-}
444
-
445
-func (ls *layerStore) Mount(name string, parent ChainID, mountLabel string, initFunc MountInit) (l RWLayer, err error) {
385
+func (ls *layerStore) CreateRWLayer(name string, parent ChainID, mountLabel string, initFunc MountInit) (RWLayer, error) {
446 386
 	ls.mountL.Lock()
447 387
 	defer ls.mountL.Unlock()
448 388
 	m, ok := ls.mounts[name]
449 389
 	if ok {
450
-		// Check if has path
451
-		if err := ls.mount(m, mountLabel); err != nil {
452
-			return nil, err
453
-		}
454
-		return m, nil
390
+		return nil, ErrMountNameConflict
455 391
 	}
456 392
 
393
+	var err error
457 394
 	var pid string
458 395
 	var p *roLayer
459 396
 	if string(parent) != "" {
... ...
@@ -473,17 +410,12 @@ func (ls *layerStore) Mount(name string, parent ChainID, mountLabel string, init
473 473
 		}()
474 474
 	}
475 475
 
476
-	mountID := name
477
-	if runtime.GOOS != "windows" {
478
-		// windows has issues if container ID doesn't match mount ID
479
-		mountID = stringid.GenerateRandomID()
480
-	}
481
-
482 476
 	m = &mountedLayer{
483 477
 		name:       name,
484 478
 		parent:     p,
485
-		mountID:    mountID,
479
+		mountID:    ls.mountID(name),
486 480
 		layerStore: ls,
481
+		references: map[RWLayer]*referencedRWLayer{},
487 482
 	}
488 483
 
489 484
 	if initFunc != nil {
... ...
@@ -502,44 +434,35 @@ func (ls *layerStore) Mount(name string, parent ChainID, mountLabel string, init
502 502
 		return nil, err
503 503
 	}
504 504
 
505
-	if err = ls.mount(m, mountLabel); err != nil {
506
-		return nil, err
507
-	}
508
-
509
-	return m, nil
505
+	return m.getReference(), nil
510 506
 }
511 507
 
512
-func (ls *layerStore) Unmount(name string) error {
508
+func (ls *layerStore) GetRWLayer(id string) (RWLayer, error) {
513 509
 	ls.mountL.Lock()
514 510
 	defer ls.mountL.Unlock()
515
-
516
-	m := ls.mounts[name]
517
-	if m == nil {
518
-		return ErrMountDoesNotExist
519
-	}
520
-
521
-	m.activityCount--
522
-
523
-	if err := ls.driver.Put(m.mountID); err != nil {
524
-		return err
511
+	mount, ok := ls.mounts[id]
512
+	if !ok {
513
+		return nil, ErrMountDoesNotExist
525 514
 	}
526 515
 
527
-	return nil
516
+	return mount.getReference(), nil
528 517
 }
529 518
 
530
-func (ls *layerStore) DeleteMount(name string) ([]Metadata, error) {
519
+func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) {
531 520
 	ls.mountL.Lock()
532 521
 	defer ls.mountL.Unlock()
533
-
534
-	m := ls.mounts[name]
535
-	if m == nil {
536
-		return nil, ErrMountDoesNotExist
522
+	m, ok := ls.mounts[l.Name()]
523
+	if !ok {
524
+		return []Metadata{}, nil
537 525
 	}
538
-	if m.activityCount > 0 {
539
-		return nil, ErrActiveMount
526
+
527
+	if err := m.deleteReference(l); err != nil {
528
+		return nil, err
540 529
 	}
541 530
 
542
-	delete(ls.mounts, name)
531
+	if m.hasReferences() {
532
+		return []Metadata{}, nil
533
+	}
543 534
 
544 535
 	if err := ls.driver.Remove(m.mountID); err != nil {
545 536
 		logrus.Errorf("Error removing mounted layer %s: %s", m.name, err)
... ...
@@ -558,6 +481,8 @@ func (ls *layerStore) DeleteMount(name string) ([]Metadata, error) {
558 558
 		return nil, err
559 559
 	}
560 560
 
561
+	delete(ls.mounts, m.Name())
562
+
561 563
 	ls.layerL.Lock()
562 564
 	defer ls.layerL.Unlock()
563 565
 	if m.parent != nil {
... ...
@@ -567,18 +492,53 @@ func (ls *layerStore) DeleteMount(name string) ([]Metadata, error) {
567 567
 	return []Metadata{}, nil
568 568
 }
569 569
 
570
-func (ls *layerStore) Changes(name string) ([]archive.Change, error) {
571
-	ls.mountL.Lock()
572
-	m := ls.mounts[name]
573
-	ls.mountL.Unlock()
574
-	if m == nil {
575
-		return nil, ErrMountDoesNotExist
570
+func (ls *layerStore) saveMount(mount *mountedLayer) error {
571
+	if err := ls.store.SetMountID(mount.name, mount.mountID); err != nil {
572
+		return err
576 573
 	}
577
-	pid := m.initID
578
-	if pid == "" && m.parent != nil {
579
-		pid = m.parent.cacheID
574
+
575
+	if mount.initID != "" {
576
+		if err := ls.store.SetInitID(mount.name, mount.initID); err != nil {
577
+			return err
578
+		}
580 579
 	}
581
-	return ls.driver.Changes(m.mountID, pid)
580
+
581
+	if mount.parent != nil {
582
+		if err := ls.store.SetMountParent(mount.name, mount.parent.chainID); err != nil {
583
+			return err
584
+		}
585
+	}
586
+
587
+	ls.mounts[mount.name] = mount
588
+
589
+	return nil
590
+}
591
+
592
+func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit) (string, error) {
593
+	// Use "<graph-id>-init" to maintain compatibility with graph drivers
594
+	// which are expecting this layer with this special name. If all
595
+	// graph drivers can be updated to not rely on knowing about this layer
596
+	// then the initID should be randomly generated.
597
+	initID := fmt.Sprintf("%s-init", graphID)
598
+
599
+	if err := ls.driver.Create(initID, parent, mountLabel); err != nil {
600
+		return "", err
601
+	}
602
+	p, err := ls.driver.Get(initID, "")
603
+	if err != nil {
604
+		return "", err
605
+	}
606
+
607
+	if err := initFunc(p); err != nil {
608
+		ls.driver.Put(initID)
609
+		return "", err
610
+	}
611
+
612
+	if err := ls.driver.Put(initID); err != nil {
613
+		return "", err
614
+	}
615
+
616
+	return initID, nil
582 617
 }
583 618
 
584 619
 func (ls *layerStore) assembleTar(graphID string, metadata io.ReadCloser, size *int64) (io.ReadCloser, error) {
... ...
@@ -621,17 +581,6 @@ func (ls *layerStore) assembleTar(graphID string, metadata io.ReadCloser, size *
621 621
 	return pR, nil
622 622
 }
623 623
 
624
-// Metadata returns the low level metadata from the mount with the given name
625
-func (ls *layerStore) Metadata(name string) (map[string]string, error) {
626
-	ls.mountL.Lock()
627
-	m := ls.mounts[name]
628
-	ls.mountL.Unlock()
629
-	if m == nil {
630
-		return nil, ErrMountDoesNotExist
631
-	}
632
-	return ls.driver.GetMetadata(m.mountID)
633
-}
634
-
635 624
 type naiveDiffPathDriver struct {
636 625
 	graphdriver.Driver
637 626
 }
... ...
@@ -82,12 +82,12 @@ type layerInit func(root string) error
82 82
 
83 83
 func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) {
84 84
 	containerID := stringid.GenerateRandomID()
85
-	mount, err := ls.Mount(containerID, parent, "", nil)
85
+	mount, err := ls.CreateRWLayer(containerID, parent, "", nil)
86 86
 	if err != nil {
87 87
 		return nil, err
88 88
 	}
89 89
 
90
-	path, err := mount.Path()
90
+	path, err := mount.Mount("")
91 91
 	if err != nil {
92 92
 		return nil, err
93 93
 	}
... ...
@@ -107,11 +107,11 @@ func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) {
107 107
 		return nil, err
108 108
 	}
109 109
 
110
-	if err := ls.Unmount(containerID); err != nil {
110
+	if err := mount.Unmount(); err != nil {
111 111
 		return nil, err
112 112
 	}
113 113
 
114
-	if _, err := ls.DeleteMount(containerID); err != nil {
114
+	if _, err := ls.ReleaseRWLayer(mount); err != nil {
115 115
 		return nil, err
116 116
 	}
117 117
 
... ...
@@ -171,6 +171,13 @@ func getCachedLayer(l Layer) *roLayer {
171 171
 	return l.(*roLayer)
172 172
 }
173 173
 
174
+func getMountLayer(l RWLayer) *mountedLayer {
175
+	if rl, ok := l.(*referencedRWLayer); ok {
176
+		return rl.mountedLayer
177
+	}
178
+	return l.(*mountedLayer)
179
+}
180
+
174 181
 func createMetadata(layers ...Layer) []Metadata {
175 182
 	metadata := make([]Metadata, len(layers))
176 183
 	for i := range layers {
... ...
@@ -270,12 +277,12 @@ func TestMountAndRegister(t *testing.T) {
270 270
 	size, _ := layer.Size()
271 271
 	t.Logf("Layer size: %d", size)
272 272
 
273
-	mount2, err := ls.Mount("new-test-mount", layer.ChainID(), "", nil)
273
+	mount2, err := ls.CreateRWLayer("new-test-mount", layer.ChainID(), "", nil)
274 274
 	if err != nil {
275 275
 		t.Fatal(err)
276 276
 	}
277 277
 
278
-	path2, err := mount2.Path()
278
+	path2, err := mount2.Mount("")
279 279
 	if err != nil {
280 280
 		t.Fatal(err)
281 281
 	}
... ...
@@ -289,11 +296,11 @@ func TestMountAndRegister(t *testing.T) {
289 289
 		t.Fatalf("Wrong file data, expected %q, got %q", expected, string(b))
290 290
 	}
291 291
 
292
-	if err := ls.Unmount("new-test-mount"); err != nil {
292
+	if err := mount2.Unmount(); err != nil {
293 293
 		t.Fatal(err)
294 294
 	}
295 295
 
296
-	if _, err := ls.DeleteMount("new-test-mount"); err != nil {
296
+	if _, err := ls.ReleaseRWLayer(mount2); err != nil {
297 297
 		t.Fatal(err)
298 298
 	}
299 299
 }
... ...
@@ -370,12 +377,12 @@ func TestStoreRestore(t *testing.T) {
370 370
 		t.Fatal(err)
371 371
 	}
372 372
 
373
-	m, err := ls.Mount("some-mount_name", layer3.ChainID(), "", nil)
373
+	m, err := ls.CreateRWLayer("some-mount_name", layer3.ChainID(), "", nil)
374 374
 	if err != nil {
375 375
 		t.Fatal(err)
376 376
 	}
377 377
 
378
-	path, err := m.Path()
378
+	path, err := m.Mount("")
379 379
 	if err != nil {
380 380
 		t.Fatal(err)
381 381
 	}
... ...
@@ -383,11 +390,14 @@ func TestStoreRestore(t *testing.T) {
383 383
 	if err := ioutil.WriteFile(filepath.Join(path, "testfile.txt"), []byte("nothing here"), 0644); err != nil {
384 384
 		t.Fatal(err)
385 385
 	}
386
+	assertActivityCount(t, m, 1)
386 387
 
387
-	if err := ls.Unmount("some-mount_name"); err != nil {
388
+	if err := m.Unmount(); err != nil {
388 389
 		t.Fatal(err)
389 390
 	}
390 391
 
392
+	assertActivityCount(t, m, 0)
393
+
391 394
 	ls2, err := NewStore(ls.(*layerStore).store, ls.(*layerStore).driver)
392 395
 	if err != nil {
393 396
 		t.Fatal(err)
... ...
@@ -400,18 +410,39 @@ func TestStoreRestore(t *testing.T) {
400 400
 
401 401
 	assertLayerEqual(t, layer3b, layer3)
402 402
 
403
-	// Mount again with same name, should already be loaded
404
-	m2, err := ls2.Mount("some-mount_name", layer3b.ChainID(), "", nil)
405
-	if err != nil {
403
+	// Create again with same name, should return error
404
+	if _, err := ls2.CreateRWLayer("some-mount_name", layer3b.ChainID(), "", nil); err == nil {
405
+		t.Fatal("Expected error creating mount with same name")
406
+	} else if err != ErrMountNameConflict {
406 407
 		t.Fatal(err)
407 408
 	}
408 409
 
409
-	path2, err := m2.Path()
410
+	m2, err := ls2.GetRWLayer("some-mount_name")
410 411
 	if err != nil {
411 412
 		t.Fatal(err)
412 413
 	}
413 414
 
414
-	b, err := ioutil.ReadFile(filepath.Join(path2, "testfile.txt"))
415
+	if mountPath, err := m2.Mount(""); err != nil {
416
+		t.Fatal(err)
417
+	} else if path != mountPath {
418
+		t.Fatalf("Unexpected path %s, expected %s", mountPath, path)
419
+	}
420
+
421
+	assertActivityCount(t, m2, 1)
422
+
423
+	if mountPath, err := m2.Mount(""); err != nil {
424
+		t.Fatal(err)
425
+	} else if path != mountPath {
426
+		t.Fatalf("Unexpected path %s, expected %s", mountPath, path)
427
+	}
428
+	assertActivityCount(t, m2, 2)
429
+	if err := m2.Unmount(); err != nil {
430
+		t.Fatal(err)
431
+	}
432
+
433
+	assertActivityCount(t, m2, 1)
434
+
435
+	b, err := ioutil.ReadFile(filepath.Join(path, "testfile.txt"))
415 436
 	if err != nil {
416 437
 		t.Fatal(err)
417 438
 	}
... ...
@@ -419,11 +450,19 @@ func TestStoreRestore(t *testing.T) {
419 419
 		t.Fatalf("Unexpected content %q, expected %q", string(b), expected)
420 420
 	}
421 421
 
422
-	if err := ls2.Unmount("some-mount_name"); err != nil {
422
+	if err := m2.Unmount(); err != nil {
423
+		t.Fatal(err)
424
+	}
425
+
426
+	assertActivityCount(t, m2, 0)
427
+
428
+	if metadata, err := ls2.ReleaseRWLayer(m2); err != nil {
423 429
 		t.Fatal(err)
430
+	} else if len(metadata) != 0 {
431
+		t.Fatalf("Unexpectedly deleted layers: %#v", metadata)
424 432
 	}
425 433
 
426
-	if metadata, err := ls2.DeleteMount("some-mount_name"); err != nil {
434
+	if metadata, err := ls2.ReleaseRWLayer(m2); err != nil {
427 435
 		t.Fatal(err)
428 436
 	} else if len(metadata) != 0 {
429 437
 		t.Fatalf("Unexpectedly deleted layers: %#v", metadata)
... ...
@@ -627,6 +666,13 @@ func assertReferences(t *testing.T, references ...Layer) {
627 627
 	}
628 628
 }
629 629
 
630
+func assertActivityCount(t *testing.T, l RWLayer, expected int) {
631
+	rl := l.(*referencedRWLayer)
632
+	if rl.activityCount != expected {
633
+		t.Fatalf("Unexpected activity count %d, expected %d", rl.activityCount, expected)
634
+	}
635
+}
636
+
630 637
 func TestRegisterExistingLayer(t *testing.T) {
631 638
 	ls, cleanup := newTestStore(t)
632 639
 	defer cleanup()
633 640
new file mode 100644
... ...
@@ -0,0 +1,9 @@
0
+// +build linux freebsd darwin
1
+
2
+package layer
3
+
4
+import "github.com/docker/docker/pkg/stringid"
5
+
6
+func (ls *layerStore) mountID(name string) string {
7
+	return stringid.GenerateRandomID()
8
+}
... ...
@@ -89,3 +89,8 @@ func (ls *layerStore) RegisterDiffID(graphID string, size int64) (Layer, error)
89 89
 
90 90
 	return layer.getReference(), nil
91 91
 }
92
+
93
+func (ls *layerStore) mountID(name string) string {
94
+	// windows has issues if container ID doesn't match mount ID
95
+	return name
96
+}
... ...
@@ -14,30 +14,33 @@ import (
14 14
 	"github.com/vbatts/tar-split/tar/storage"
15 15
 )
16 16
 
17
-func (ls *layerStore) MountByGraphID(name string, graphID string, parent ChainID) (l RWLayer, err error) {
17
+// CreateRWLayerByGraphID creates a RWLayer in the layer store using
18
+// the provided name with the given graphID. To get the RWLayer
19
+// after migration the layer may be retrieved by the given name.
20
+func (ls *layerStore) CreateRWLayerByGraphID(name string, graphID string, parent ChainID) (err error) {
18 21
 	ls.mountL.Lock()
19 22
 	defer ls.mountL.Unlock()
20 23
 	m, ok := ls.mounts[name]
21 24
 	if ok {
22 25
 		if m.parent.chainID != parent {
23
-			return nil, errors.New("name conflict, mismatched parent")
26
+			return errors.New("name conflict, mismatched parent")
24 27
 		}
25 28
 		if m.mountID != graphID {
26
-			return nil, errors.New("mount already exists")
29
+			return errors.New("mount already exists")
27 30
 		}
28 31
 
29
-		return m, nil
32
+		return nil
30 33
 	}
31 34
 
32 35
 	if !ls.driver.Exists(graphID) {
33
-		return nil, errors.New("graph ID does not exist")
36
+		return errors.New("graph ID does not exist")
34 37
 	}
35 38
 
36 39
 	var p *roLayer
37 40
 	if string(parent) != "" {
38 41
 		p = ls.get(parent)
39 42
 		if p == nil {
40
-			return nil, ErrLayerDoesNotExist
43
+			return ErrLayerDoesNotExist
41 44
 		}
42 45
 
43 46
 		// Release parent chain if error
... ...
@@ -57,6 +60,7 @@ func (ls *layerStore) MountByGraphID(name string, graphID string, parent ChainID
57 57
 		parent:     p,
58 58
 		mountID:    graphID,
59 59
 		layerStore: ls,
60
+		references: map[RWLayer]*referencedRWLayer{},
60 61
 	}
61 62
 
62 63
 	// Check for existing init layer
... ...
@@ -66,15 +70,10 @@ func (ls *layerStore) MountByGraphID(name string, graphID string, parent ChainID
66 66
 	}
67 67
 
68 68
 	if err = ls.saveMount(m); err != nil {
69
-		return nil, err
70
-	}
71
-
72
-	// TODO: provide a mount label
73
-	if err = ls.mount(m, ""); err != nil {
74
-		return nil, err
69
+		return err
75 70
 	}
76 71
 
77
-	return m, nil
72
+	return nil
78 73
 }
79 74
 
80 75
 func (ls *layerStore) migrateLayer(tx MetadataTransaction, tarDataFile string, layer *roLayer) error {
... ...
@@ -303,12 +303,20 @@ func TestMountMigration(t *testing.T) {
303 303
 		t.Fatal(err)
304 304
 	}
305 305
 
306
-	rwLayer1, err := ls.(*layerStore).MountByGraphID("migration-mount", containerID, layer1.ChainID())
306
+	if err := ls.(*layerStore).CreateRWLayerByGraphID("migration-mount", containerID, layer1.ChainID()); err != nil {
307
+		t.Fatal(err)
308
+	}
309
+
310
+	rwLayer1, err := ls.GetRWLayer("migration-mount")
307 311
 	if err != nil {
308 312
 		t.Fatal(err)
309 313
 	}
310 314
 
311
-	changes, err := ls.Changes("migration-mount")
315
+	if _, err := rwLayer1.Mount(""); err != nil {
316
+		t.Fatal(err)
317
+	}
318
+
319
+	changes, err := rwLayer1.Changes()
312 320
 	if err != nil {
313 321
 		t.Fatal(err)
314 322
 	}
... ...
@@ -341,39 +349,63 @@ func TestMountMigration(t *testing.T) {
341 341
 		Kind: archive.ChangeAdd,
342 342
 	})
343 343
 
344
-	if expectedCount := 1; rwLayer1.(*mountedLayer).activityCount != expectedCount {
345
-		t.Fatalf("Wrong activity count %d, expected %d", rwLayer1.(*mountedLayer).activityCount, expectedCount)
344
+	assertActivityCount(t, rwLayer1, 1)
345
+
346
+	if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), "", nil); err == nil {
347
+		t.Fatal("Expected error creating mount with same name")
348
+	} else if err != ErrMountNameConflict {
349
+		t.Fatal(err)
346 350
 	}
347 351
 
348
-	rwLayer2, err := ls.Mount("migration-mount", layer1.ChainID(), "", nil)
352
+	rwLayer2, err := ls.GetRWLayer("migration-mount")
349 353
 	if err != nil {
350 354
 		t.Fatal(err)
351 355
 	}
352 356
 
353
-	if rwLayer1 != rwLayer2 {
354
-		t.Fatalf("Wrong rwlayer %v, expected %v", rwLayer2, rwLayer1)
357
+	if getMountLayer(rwLayer1) != getMountLayer(rwLayer2) {
358
+		t.Fatal("Expected same layer from get with same name as from migrate")
359
+	}
360
+
361
+	if _, err := rwLayer2.Mount(""); err != nil {
362
+		t.Fatal(err)
355 363
 	}
356 364
 
357
-	if expectedCount := 2; rwLayer2.(*mountedLayer).activityCount != expectedCount {
358
-		t.Fatalf("Wrong activity count %d, expected %d", rwLayer2.(*mountedLayer).activityCount, expectedCount)
365
+	assertActivityCount(t, rwLayer2, 1)
366
+	assertActivityCount(t, rwLayer1, 1)
367
+
368
+	if _, err := rwLayer2.Mount(""); err != nil {
369
+		t.Fatal(err)
359 370
 	}
360 371
 
372
+	assertActivityCount(t, rwLayer2, 2)
373
+	assertActivityCount(t, rwLayer1, 1)
374
+
361 375
 	if metadata, err := ls.Release(layer1); err != nil {
362 376
 		t.Fatal(err)
363 377
 	} else if len(metadata) > 0 {
364 378
 		t.Fatalf("Expected no layers to be deleted, deleted %#v", metadata)
365 379
 	}
366 380
 
367
-	if err := ls.Unmount("migration-mount"); err != nil {
381
+	if err := rwLayer1.Unmount(); err != nil {
382
+		t.Fatal(err)
383
+	}
384
+	assertActivityCount(t, rwLayer2, 2)
385
+	assertActivityCount(t, rwLayer1, 0)
386
+
387
+	if _, err := ls.ReleaseRWLayer(rwLayer1); err != nil {
388
+		t.Fatal(err)
389
+	}
390
+
391
+	if err := rwLayer2.Unmount(); err != nil {
368 392
 		t.Fatal(err)
369 393
 	}
370
-	if _, err := ls.DeleteMount("migration-mount"); err == nil {
394
+	if _, err := ls.ReleaseRWLayer(rwLayer2); err == nil {
371 395
 		t.Fatal("Expected error deleting active mount")
372 396
 	}
373
-	if err := ls.Unmount("migration-mount"); err != nil {
397
+	if err := rwLayer2.Unmount(); err != nil {
374 398
 		t.Fatal(err)
375 399
 	}
376
-	metadata, err := ls.DeleteMount("migration-mount")
400
+	metadata, err := ls.ReleaseRWLayer(rwLayer2)
377 401
 	if err != nil {
378 402
 		t.Fatal(err)
379 403
 	}
... ...
@@ -27,12 +27,12 @@ func TestMountInit(t *testing.T) {
27 27
 		return initfile.ApplyFile(root)
28 28
 	}
29 29
 
30
-	m, err := ls.Mount("fun-mount", layer.ChainID(), "", mountInit)
30
+	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), "", mountInit)
31 31
 	if err != nil {
32 32
 		t.Fatal(err)
33 33
 	}
34 34
 
35
-	path, err := m.Path()
35
+	path, err := m.Mount("")
36 36
 	if err != nil {
37 37
 		t.Fatal(err)
38 38
 	}
... ...
@@ -80,12 +80,12 @@ func TestMountSize(t *testing.T) {
80 80
 		return newTestFile("file-init", contentInit, 0777).ApplyFile(root)
81 81
 	}
82 82
 
83
-	m, err := ls.Mount("mount-size", layer.ChainID(), "", mountInit)
83
+	m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), "", mountInit)
84 84
 	if err != nil {
85 85
 		t.Fatal(err)
86 86
 	}
87 87
 
88
-	path, err := m.Path()
88
+	path, err := m.Mount("")
89 89
 	if err != nil {
90 90
 		t.Fatal(err)
91 91
 	}
... ...
@@ -125,12 +125,12 @@ func TestMountChanges(t *testing.T) {
125 125
 		return initfile.ApplyFile(root)
126 126
 	}
127 127
 
128
-	m, err := ls.Mount("mount-changes", layer.ChainID(), "", mountInit)
128
+	m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), "", mountInit)
129 129
 	if err != nil {
130 130
 		t.Fatal(err)
131 131
 	}
132 132
 
133
-	path, err := m.Path()
133
+	path, err := m.Mount("")
134 134
 	if err != nil {
135 135
 		t.Fatal(err)
136 136
 	}
... ...
@@ -155,7 +155,7 @@ func TestMountChanges(t *testing.T) {
155 155
 		t.Fatal(err)
156 156
 	}
157 157
 
158
-	changes, err := ls.Changes("mount-changes")
158
+	changes, err := m.Changes()
159 159
 	if err != nil {
160 160
 		t.Fatal(err)
161 161
 	}
... ...
@@ -1,15 +1,20 @@
1 1
 package layer
2 2
 
3
-import "io"
3
+import (
4
+	"io"
5
+	"sync"
6
+
7
+	"github.com/docker/docker/pkg/archive"
8
+)
4 9
 
5 10
 type mountedLayer struct {
6
-	name          string
7
-	mountID       string
8
-	initID        string
9
-	parent        *roLayer
10
-	path          string
11
-	layerStore    *layerStore
12
-	activityCount int
11
+	name       string
12
+	mountID    string
13
+	initID     string
14
+	parent     *roLayer
15
+	layerStore *layerStore
16
+
17
+	references map[RWLayer]*referencedRWLayer
13 18
 }
14 19
 
15 20
 func (ml *mountedLayer) cacheParent() string {
... ...
@@ -30,11 +35,8 @@ func (ml *mountedLayer) TarStream() (io.ReadCloser, error) {
30 30
 	return archiver, nil
31 31
 }
32 32
 
33
-func (ml *mountedLayer) Path() (string, error) {
34
-	if ml.path == "" {
35
-		return "", ErrNotMounted
36
-	}
37
-	return ml.path, nil
33
+func (ml *mountedLayer) Name() string {
34
+	return ml.name
38 35
 }
39 36
 
40 37
 func (ml *mountedLayer) Parent() Layer {
... ...
@@ -47,6 +49,96 @@ func (ml *mountedLayer) Parent() Layer {
47 47
 	return nil
48 48
 }
49 49
 
50
+func (ml *mountedLayer) Mount(mountLabel string) (string, error) {
51
+	return ml.layerStore.driver.Get(ml.mountID, mountLabel)
52
+}
53
+
54
+func (ml *mountedLayer) Unmount() error {
55
+	return ml.layerStore.driver.Put(ml.mountID)
56
+}
57
+
50 58
 func (ml *mountedLayer) Size() (int64, error) {
51 59
 	return ml.layerStore.driver.DiffSize(ml.mountID, ml.cacheParent())
52 60
 }
61
+
62
+func (ml *mountedLayer) Changes() ([]archive.Change, error) {
63
+	return ml.layerStore.driver.Changes(ml.mountID, ml.cacheParent())
64
+}
65
+
66
+func (ml *mountedLayer) Metadata() (map[string]string, error) {
67
+	return ml.layerStore.driver.GetMetadata(ml.mountID)
68
+}
69
+
70
+func (ml *mountedLayer) getReference() RWLayer {
71
+	ref := &referencedRWLayer{
72
+		mountedLayer: ml,
73
+	}
74
+	ml.references[ref] = ref
75
+
76
+	return ref
77
+}
78
+
79
+func (ml *mountedLayer) hasReferences() bool {
80
+	return len(ml.references) > 0
81
+}
82
+
83
+func (ml *mountedLayer) deleteReference(ref RWLayer) error {
84
+	rl, ok := ml.references[ref]
85
+	if !ok {
86
+		return ErrLayerNotRetained
87
+	}
88
+
89
+	if err := rl.release(); err != nil {
90
+		return err
91
+	}
92
+	delete(ml.references, ref)
93
+
94
+	return nil
95
+}
96
+
97
+type referencedRWLayer struct {
98
+	*mountedLayer
99
+
100
+	activityL     sync.Mutex
101
+	activityCount int
102
+}
103
+
104
+func (rl *referencedRWLayer) release() error {
105
+	rl.activityL.Lock()
106
+	defer rl.activityL.Unlock()
107
+
108
+	if rl.activityCount > 0 {
109
+		return ErrActiveMount
110
+	}
111
+
112
+	rl.activityCount = -1
113
+
114
+	return nil
115
+}
116
+
117
+func (rl *referencedRWLayer) Mount(mountLabel string) (string, error) {
118
+	rl.activityL.Lock()
119
+	defer rl.activityL.Unlock()
120
+
121
+	if rl.activityCount == -1 {
122
+		return "", ErrLayerNotRetained
123
+	}
124
+
125
+	rl.activityCount++
126
+	return rl.mountedLayer.Mount(mountLabel)
127
+}
128
+
129
+func (rl *referencedRWLayer) Unmount() error {
130
+	rl.activityL.Lock()
131
+	defer rl.activityL.Unlock()
132
+
133
+	if rl.activityCount == 0 {
134
+		return ErrNotMounted
135
+	}
136
+	if rl.activityCount == -1 {
137
+		return ErrLayerNotRetained
138
+	}
139
+	rl.activityCount--
140
+
141
+	return rl.mountedLayer.Unmount()
142
+}
... ...
@@ -24,8 +24,7 @@ type graphIDRegistrar interface {
24 24
 }
25 25
 
26 26
 type graphIDMounter interface {
27
-	MountByGraphID(string, string, layer.ChainID) (layer.RWLayer, error)
28
-	Unmount(string) error
27
+	CreateRWLayerByGraphID(string, string, layer.ChainID) error
29 28
 }
30 29
 
31 30
 const (
... ...
@@ -172,13 +171,7 @@ func migrateContainers(root string, ls graphIDMounter, is image.Store, imageMapp
172 172
 			return err
173 173
 		}
174 174
 
175
-		_, err = ls.MountByGraphID(id, id, img.RootFS.ChainID())
176
-		if err != nil {
177
-			return err
178
-		}
179
-
180
-		err = ls.Unmount(id)
181
-		if err != nil {
175
+		if err := ls.CreateRWLayerByGraphID(id, id, img.RootFS.ChainID()); err != nil {
182 176
 			return err
183 177
 		}
184 178
 
... ...
@@ -338,10 +338,9 @@ type mockMounter struct {
338 338
 	count  int
339 339
 }
340 340
 
341
-func (r *mockMounter) MountByGraphID(name string, graphID string, parent layer.ChainID) (layer.RWLayer, error) {
341
+func (r *mockMounter) CreateRWLayerByGraphID(name string, graphID string, parent layer.ChainID) error {
342 342
 	r.mounts = append(r.mounts, mountInfo{name, graphID, string(parent)})
343
-	r.count++
344
-	return nil, nil
343
+	return nil
345 344
 }
346 345
 func (r *mockMounter) Unmount(string) error {
347 346
 	r.count--