Browse code

Add more locking to storage drivers

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2017/02/18 08:46:19
Showing 4 changed files
... ...
@@ -44,6 +44,7 @@ import (
44 44
 	"github.com/docker/docker/pkg/chrootarchive"
45 45
 	"github.com/docker/docker/pkg/directory"
46 46
 	"github.com/docker/docker/pkg/idtools"
47
+	"github.com/docker/docker/pkg/locker"
47 48
 	mountpk "github.com/docker/docker/pkg/mount"
48 49
 
49 50
 	"github.com/opencontainers/runc/libcontainer/label"
... ...
@@ -75,6 +76,7 @@ type Driver struct {
75 75
 	pathCacheLock sync.Mutex
76 76
 	pathCache     map[string]string
77 77
 	naiveDiff     graphdriver.DiffDriver
78
+	locker        *locker.Locker
78 79
 }
79 80
 
80 81
 // Init returns a new AUFS driver.
... ...
@@ -112,6 +114,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
112 112
 		gidMaps:   gidMaps,
113 113
 		pathCache: make(map[string]string),
114 114
 		ctr:       graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicAufs)),
115
+		locker:    locker.New(),
115 116
 	}
116 117
 
117 118
 	rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps)
... ...
@@ -304,6 +307,8 @@ func debugEBusy(mountPath string) (out []string, err error) {
304 304
 
305 305
 // Remove will unmount and remove the given id.
306 306
 func (a *Driver) Remove(id string) error {
307
+	a.locker.Lock(id)
308
+	defer a.locker.Unlock(id)
307 309
 	a.pathCacheLock.Lock()
308 310
 	mountpoint, exists := a.pathCache[id]
309 311
 	a.pathCacheLock.Unlock()
... ...
@@ -377,6 +382,8 @@ func (a *Driver) Remove(id string) error {
377 377
 // Get returns the rootfs path for the id.
378 378
 // This will mount the dir at its given path
379 379
 func (a *Driver) Get(id, mountLabel string) (string, error) {
380
+	a.locker.Lock(id)
381
+	defer a.locker.Unlock(id)
380 382
 	parents, err := a.getParentLayerPaths(id)
381 383
 	if err != nil && !os.IsNotExist(err) {
382 384
 		return "", err
... ...
@@ -412,6 +419,8 @@ func (a *Driver) Get(id, mountLabel string) (string, error) {
412 412
 
413 413
 // Put unmounts and updates list of active mounts.
414 414
 func (a *Driver) Put(id string) error {
415
+	a.locker.Lock(id)
416
+	defer a.locker.Unlock(id)
415 417
 	a.pathCacheLock.Lock()
416 418
 	m, exists := a.pathCache[id]
417 419
 	if !exists {
... ...
@@ -14,8 +14,9 @@ import (
14 14
 	"github.com/docker/docker/daemon/graphdriver"
15 15
 	"github.com/docker/docker/pkg/devicemapper"
16 16
 	"github.com/docker/docker/pkg/idtools"
17
+	"github.com/docker/docker/pkg/locker"
17 18
 	"github.com/docker/docker/pkg/mount"
18
-	"github.com/docker/go-units"
19
+	units "github.com/docker/go-units"
19 20
 )
20 21
 
21 22
 func init() {
... ...
@@ -29,6 +30,7 @@ type Driver struct {
29 29
 	uidMaps []idtools.IDMap
30 30
 	gidMaps []idtools.IDMap
31 31
 	ctr     *graphdriver.RefCounter
32
+	locker  *locker.Locker
32 33
 }
33 34
 
34 35
 // Init creates a driver with the given home and the set of options.
... ...
@@ -48,6 +50,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
48 48
 		uidMaps:   uidMaps,
49 49
 		gidMaps:   gidMaps,
50 50
 		ctr:       graphdriver.NewRefCounter(graphdriver.NewDefaultChecker()),
51
+		locker:    locker.New(),
51 52
 	}
52 53
 
53 54
 	return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil
... ...
@@ -142,6 +145,8 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
142 142
 
143 143
 // Remove removes a device with a given id, unmounts the filesystem.
144 144
 func (d *Driver) Remove(id string) error {
145
+	d.locker.Lock(id)
146
+	defer d.locker.Unlock(id)
145 147
 	if !d.DeviceSet.HasDevice(id) {
146 148
 		// Consider removing a non-existing device a no-op
147 149
 		// This is useful to be able to progress on container removal
... ...
@@ -164,6 +169,8 @@ func (d *Driver) Remove(id string) error {
164 164
 
165 165
 // Get mounts a device with given id into the root filesystem
166 166
 func (d *Driver) Get(id, mountLabel string) (string, error) {
167
+	d.locker.Lock(id)
168
+	defer d.locker.Unlock(id)
167 169
 	mp := path.Join(d.home, "mnt", id)
168 170
 	rootFs := path.Join(mp, "rootfs")
169 171
 	if count := d.ctr.Increment(mp); count > 1 {
... ...
@@ -214,6 +221,8 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
214 214
 
215 215
 // Put unmounts a device and removes it.
216 216
 func (d *Driver) Put(id string) error {
217
+	d.locker.Lock(id)
218
+	defer d.locker.Unlock(id)
217 219
 	mp := path.Join(d.home, "mnt", id)
218 220
 	if count := d.ctr.Decrement(mp); count > 0 {
219 221
 		return nil
... ...
@@ -19,6 +19,7 @@ import (
19 19
 	"github.com/docker/docker/pkg/archive"
20 20
 	"github.com/docker/docker/pkg/fsutils"
21 21
 	"github.com/docker/docker/pkg/idtools"
22
+	"github.com/docker/docker/pkg/locker"
22 23
 	"github.com/docker/docker/pkg/mount"
23 24
 	"github.com/opencontainers/runc/libcontainer/label"
24 25
 )
... ...
@@ -97,6 +98,7 @@ type Driver struct {
97 97
 	gidMaps       []idtools.IDMap
98 98
 	ctr           *graphdriver.RefCounter
99 99
 	supportsDType bool
100
+	locker        *locker.Locker
100 101
 }
101 102
 
102 103
 func init() {
... ...
@@ -154,6 +156,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
154 154
 		gidMaps:       gidMaps,
155 155
 		ctr:           graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
156 156
 		supportsDType: supportsDType,
157
+		locker:        locker.New(),
157 158
 	}
158 159
 
159 160
 	return NaiveDiffDriverWithApply(d, uidMaps, gidMaps), nil
... ...
@@ -334,6 +337,8 @@ func (d *Driver) dir(id string) string {
334 334
 
335 335
 // Remove cleans the directories that are created for this id.
336 336
 func (d *Driver) Remove(id string) error {
337
+	d.locker.Lock(id)
338
+	defer d.locker.Unlock(id)
337 339
 	if err := os.RemoveAll(d.dir(id)); err != nil && !os.IsNotExist(err) {
338 340
 		return err
339 341
 	}
... ...
@@ -342,6 +347,8 @@ func (d *Driver) Remove(id string) error {
342 342
 
343 343
 // Get creates and mounts the required file system for the given id and returns the mount path.
344 344
 func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
345
+	d.locker.Lock(id)
346
+	defer d.locker.Unlock(id)
345 347
 	dir := d.dir(id)
346 348
 	if _, err := os.Stat(dir); err != nil {
347 349
 		return "", err
... ...
@@ -389,6 +396,8 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
389 389
 
390 390
 // Put unmounts the mount path created for the give id.
391 391
 func (d *Driver) Put(id string) error {
392
+	d.locker.Lock(id)
393
+	defer d.locker.Unlock(id)
392 394
 	// If id has a root, just return
393 395
 	if _, err := os.Stat(path.Join(d.dir(id), "root")); err == nil {
394 396
 		return nil
... ...
@@ -27,6 +27,7 @@ import (
27 27
 	"github.com/docker/docker/pkg/directory"
28 28
 	"github.com/docker/docker/pkg/fsutils"
29 29
 	"github.com/docker/docker/pkg/idtools"
30
+	"github.com/docker/docker/pkg/locker"
30 31
 	"github.com/docker/docker/pkg/mount"
31 32
 	"github.com/docker/docker/pkg/parsers"
32 33
 	"github.com/docker/docker/pkg/parsers/kernel"
... ...
@@ -98,6 +99,7 @@ type Driver struct {
98 98
 	options       overlayOptions
99 99
 	naiveDiff     graphdriver.DiffDriver
100 100
 	supportsDType bool
101
+	locker        *locker.Locker
101 102
 }
102 103
 
103 104
 var (
... ...
@@ -180,6 +182,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
180 180
 		gidMaps:       gidMaps,
181 181
 		ctr:           graphdriver.NewRefCounter(graphdriver.NewFsChecker(graphdriver.FsMagicOverlay)),
182 182
 		supportsDType: supportsDType,
183
+		locker:        locker.New(),
183 184
 	}
184 185
 
185 186
 	d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps)
... ...
@@ -451,6 +454,8 @@ func (d *Driver) getLowerDirs(id string) ([]string, error) {
451 451
 
452 452
 // Remove cleans the directories that are created for this id.
453 453
 func (d *Driver) Remove(id string) error {
454
+	d.locker.Lock(id)
455
+	defer d.locker.Unlock(id)
454 456
 	dir := d.dir(id)
455 457
 	lid, err := ioutil.ReadFile(path.Join(dir, "link"))
456 458
 	if err == nil {
... ...
@@ -467,6 +472,8 @@ func (d *Driver) Remove(id string) error {
467 467
 
468 468
 // Get creates and mounts the required file system for the given id and returns the mount path.
469 469
 func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
470
+	d.locker.Lock(id)
471
+	defer d.locker.Unlock(id)
470 472
 	dir := d.dir(id)
471 473
 	if _, err := os.Stat(dir); err != nil {
472 474
 		return "", err
... ...
@@ -553,6 +560,8 @@ func (d *Driver) Get(id string, mountLabel string) (s string, err error) {
553 553
 
554 554
 // Put unmounts the mount path created for the give id.
555 555
 func (d *Driver) Put(id string) error {
556
+	d.locker.Lock(id)
557
+	defer d.locker.Unlock(id)
556 558
 	dir := d.dir(id)
557 559
 	_, err := ioutil.ReadFile(path.Join(dir, lowerFile))
558 560
 	if err != nil {