Browse code

Restore ref count

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>

Michael Crosby authored on 2016/05/03 07:44:20
Showing 6 changed files
... ...
@@ -1,32 +1,69 @@
1 1
 package graphdriver
2 2
 
3
-import "sync"
3
+import (
4
+	"sync"
5
+
6
+	"github.com/docker/docker/pkg/mount"
7
+)
8
+
9
+type minfo struct {
10
+	check bool
11
+	count int
12
+}
4 13
 
5 14
 // RefCounter is a generic counter for use by graphdriver Get/Put calls
6 15
 type RefCounter struct {
7
-	counts map[string]int
16
+	counts map[string]*minfo
8 17
 	mu     sync.Mutex
9 18
 }
10 19
 
11 20
 // NewRefCounter returns a new RefCounter
12 21
 func NewRefCounter() *RefCounter {
13
-	return &RefCounter{counts: make(map[string]int)}
22
+	return &RefCounter{counts: make(map[string]*minfo)}
14 23
 }
15 24
 
16 25
 // Increment increaes the ref count for the given id and returns the current count
17
-func (c *RefCounter) Increment(id string) int {
26
+func (c *RefCounter) Increment(path string) int {
18 27
 	c.mu.Lock()
19
-	c.counts[id]++
20
-	count := c.counts[id]
28
+	m := c.counts[path]
29
+	if m == nil {
30
+		m = &minfo{check: true}
31
+		c.counts[path] = m
32
+	}
33
+	// if we are checking this path for the first time check to make sure
34
+	// if it was already mounted on the system and make sure we have a correct ref
35
+	// count if it is mounted as it is in use.
36
+	if !m.check {
37
+		m.check = true
38
+		mntd, _ := mount.Mounted(path)
39
+		if mntd {
40
+			m.count++
41
+		}
42
+	}
43
+	m.count++
21 44
 	c.mu.Unlock()
22
-	return count
45
+	return m.count
23 46
 }
24 47
 
25 48
 // Decrement decreases the ref count for the given id and returns the current count
26
-func (c *RefCounter) Decrement(id string) int {
49
+func (c *RefCounter) Decrement(path string) int {
27 50
 	c.mu.Lock()
28
-	c.counts[id]--
29
-	count := c.counts[id]
51
+	m := c.counts[path]
52
+	if m == nil {
53
+		m = &minfo{check: true}
54
+		c.counts[path] = m
55
+	}
56
+	// if we are checking this path for the first time check to make sure
57
+	// if it was already mounted on the system and make sure we have a correct ref
58
+	// count if it is mounted as it is in use.
59
+	if !m.check {
60
+		m.check = true
61
+		mntd, _ := mount.Mounted(path)
62
+		if mntd {
63
+			m.count++
64
+		}
65
+	}
66
+	m.count--
30 67
 	c.mu.Unlock()
31
-	return count
68
+	return m.count
32 69
 }
... ...
@@ -160,35 +160,35 @@ func (d *Driver) Remove(id string) error {
160 160
 // Get mounts a device with given id into the root filesystem
161 161
 func (d *Driver) Get(id, mountLabel string) (string, error) {
162 162
 	mp := path.Join(d.home, "mnt", id)
163
-	if count := d.ctr.Increment(id); count > 1 {
163
+	if count := d.ctr.Increment(mp); count > 1 {
164 164
 		return mp, nil
165 165
 	}
166 166
 
167 167
 	uid, gid, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
168 168
 	if err != nil {
169
-		d.ctr.Decrement(id)
169
+		d.ctr.Decrement(mp)
170 170
 		return "", err
171 171
 	}
172 172
 
173 173
 	// Create the target directories if they don't exist
174 174
 	if err := idtools.MkdirAllAs(path.Join(d.home, "mnt"), 0755, uid, gid); err != nil && !os.IsExist(err) {
175
-		d.ctr.Decrement(id)
175
+		d.ctr.Decrement(mp)
176 176
 		return "", err
177 177
 	}
178 178
 	if err := idtools.MkdirAs(mp, 0755, uid, gid); err != nil && !os.IsExist(err) {
179
-		d.ctr.Decrement(id)
179
+		d.ctr.Decrement(mp)
180 180
 		return "", err
181 181
 	}
182 182
 
183 183
 	// Mount the device
184 184
 	if err := d.DeviceSet.MountDevice(id, mp, mountLabel); err != nil {
185
-		d.ctr.Decrement(id)
185
+		d.ctr.Decrement(mp)
186 186
 		return "", err
187 187
 	}
188 188
 
189 189
 	rootFs := path.Join(mp, "rootfs")
190 190
 	if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
191
-		d.ctr.Decrement(id)
191
+		d.ctr.Decrement(mp)
192 192
 		d.DeviceSet.UnmountDevice(id, mp)
193 193
 		return "", err
194 194
 	}
... ...
@@ -198,7 +198,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
198 198
 		// Create an "id" file with the container/image id in it to help reconstruct this in case
199 199
 		// of later problems
200 200
 		if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil {
201
-			d.ctr.Decrement(id)
201
+			d.ctr.Decrement(mp)
202 202
 			d.DeviceSet.UnmountDevice(id, mp)
203 203
 			return "", err
204 204
 		}
... ...
@@ -209,10 +209,10 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
209 209
 
210 210
 // Put unmounts a device and removes it.
211 211
 func (d *Driver) Put(id string) error {
212
-	if count := d.ctr.Decrement(id); count > 0 {
212
+	mp := path.Join(d.home, "mnt", id)
213
+	if count := d.ctr.Decrement(mp); count > 0 {
213 214
 		return nil
214 215
 	}
215
-	mp := path.Join(d.home, "mnt", id)
216 216
 	err := d.DeviceSet.UnmountDevice(id, mp)
217 217
 	if err != nil {
218 218
 		logrus.Errorf("devmapper: Error unmounting device %s: %s", id, err)
... ...
@@ -340,6 +340,10 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) {
340 340
 	if _, err := os.Stat(dir); err != nil {
341 341
 		return "", err
342 342
 	}
343
+	mergedDir := path.Join(dir, "merged")
344
+	if count := d.ctr.Increment(mergedDir); count > 1 {
345
+		return mergedDir, nil
346
+	}
343 347
 
344 348
 	// If id has a root, just return it
345 349
 	rootDir := path.Join(dir, "root")
... ...
@@ -357,40 +361,24 @@ func (d *Driver) Get(id string, mountLabel string) (string, error) {
357 357
 	lowerDir := path.Join(d.dir(string(lowerID)), "root")
358 358
 	upperDir := path.Join(dir, "upper")
359 359
 	workDir := path.Join(dir, "work")
360
-	mergedDir := path.Join(dir, "merged")
361
-
362
-	if count := d.ctr.Increment(id); count > 1 {
363
-		return mergedDir, nil
364
-	}
365 360
 
366 361
 	opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, upperDir, workDir)
367 362
 
368
-	// if it's mounted already, just return
369
-	mounted, err := d.mounted(mergedDir)
370
-	if err != nil {
371
-		d.ctr.Decrement(id)
372
-		return "", err
373
-	}
374
-	if mounted {
375
-		d.ctr.Decrement(id)
376
-		return mergedDir, nil
377
-	}
378
-
379 363
 	if err := syscall.Mount("overlay", mergedDir, "overlay", 0, label.FormatMountLabel(opts, mountLabel)); err != nil {
380
-		d.ctr.Decrement(id)
364
+		d.ctr.Decrement(mergedDir)
381 365
 		return "", fmt.Errorf("error creating overlay mount to %s: %v", mergedDir, err)
382 366
 	}
383 367
 	// chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a
384 368
 	// user namespace requires this to move a directory from lower to upper.
385 369
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
386 370
 	if err != nil {
387
-		d.ctr.Decrement(id)
371
+		d.ctr.Decrement(mergedDir)
388 372
 		syscall.Unmount(mergedDir, 0)
389 373
 		return "", err
390 374
 	}
391 375
 
392 376
 	if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil {
393
-		d.ctr.Decrement(id)
377
+		d.ctr.Decrement(mergedDir)
394 378
 		syscall.Unmount(mergedDir, 0)
395 379
 		return "", err
396 380
 	}
... ...
@@ -408,13 +396,14 @@ func (d *Driver) mounted(dir string) (bool, error) {
408 408
 
409 409
 // Put unmounts the mount path created for the give id.
410 410
 func (d *Driver) Put(id string) error {
411
-	if count := d.ctr.Decrement(id); count > 0 {
412
-		return nil
413
-	}
414 411
 	d.pathCacheLock.Lock()
415 412
 	mountpoint, exists := d.pathCache[id]
416 413
 	d.pathCacheLock.Unlock()
417 414
 
415
+	if count := d.ctr.Decrement(mountpoint); count > 0 {
416
+		return nil
417
+	}
418
+
418 419
 	if !exists {
419 420
 		logrus.Debugf("Put on a non-mounted device %s", id)
420 421
 		// but it might be still here
... ...
@@ -307,7 +307,7 @@ func (d *Driver) Remove(id string) error {
307 307
 // Get returns the mountpoint for the given id after creating the target directories if necessary.
308 308
 func (d *Driver) Get(id, mountLabel string) (string, error) {
309 309
 	mountpoint := d.mountPath(id)
310
-	if count := d.ctr.Increment(id); count > 1 {
310
+	if count := d.ctr.Increment(mountpoint); count > 1 {
311 311
 		return mountpoint, nil
312 312
 	}
313 313
 
... ...
@@ -317,17 +317,17 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
317 317
 
318 318
 	rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
319 319
 	if err != nil {
320
-		d.ctr.Decrement(id)
320
+		d.ctr.Decrement(mountpoint)
321 321
 		return "", err
322 322
 	}
323 323
 	// Create the target directories if they don't exist
324 324
 	if err := idtools.MkdirAllAs(mountpoint, 0755, rootUID, rootGID); err != nil {
325
-		d.ctr.Decrement(id)
325
+		d.ctr.Decrement(mountpoint)
326 326
 		return "", err
327 327
 	}
328 328
 
329 329
 	if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil {
330
-		d.ctr.Decrement(id)
330
+		d.ctr.Decrement(mountpoint)
331 331
 		return "", fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err)
332 332
 	}
333 333
 
... ...
@@ -335,7 +335,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
335 335
 	// permissions instead of the remapped root uid:gid (if user namespaces are enabled):
336 336
 	if err := os.Chown(mountpoint, rootUID, rootGID); err != nil {
337 337
 		mount.Unmount(mountpoint)
338
-		d.ctr.Decrement(id)
338
+		d.ctr.Decrement(mountpoint)
339 339
 		return "", fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err)
340 340
 	}
341 341
 
... ...
@@ -344,10 +344,10 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
344 344
 
345 345
 // Put removes the existing mountpoint for the given id if it exists.
346 346
 func (d *Driver) Put(id string) error {
347
-	if count := d.ctr.Decrement(id); count > 0 {
347
+	mountpoint := d.mountPath(id)
348
+	if count := d.ctr.Decrement(mountpoint); count > 0 {
348 349
 		return nil
349 350
 	}
350
-	mountpoint := d.mountPath(id)
351 351
 	mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint)
352 352
 	if err != nil || !mounted {
353 353
 		return err
... ...
@@ -1,5 +1,3 @@
1
-// +build experimental
2
-
3 1
 package libcontainerd
4 2
 
5 3
 import (
6 4
deleted file mode 100644
... ...
@@ -1,41 +0,0 @@
1
-// +build !experimental
2
-
3
-package libcontainerd
4
-
5
-import (
6
-	"syscall"
7
-	"time"
8
-
9
-	"github.com/Sirupsen/logrus"
10
-)
11
-
12
-func (clnt *client) Restore(containerID string, options ...CreateOption) error {
13
-	w := clnt.getOrCreateExitNotifier(containerID)
14
-	defer w.close()
15
-	cont, err := clnt.getContainerdContainer(containerID)
16
-	if err == nil && cont.Status != "stopped" {
17
-		clnt.lock(cont.Id)
18
-		container := clnt.newContainer(cont.BundlePath)
19
-		container.systemPid = systemPid(cont)
20
-		clnt.appendContainer(container)
21
-		clnt.unlock(cont.Id)
22
-
23
-		if err := clnt.Signal(containerID, int(syscall.SIGTERM)); err != nil {
24
-			logrus.Errorf("error sending sigterm to %v: %v", containerID, err)
25
-		}
26
-		select {
27
-		case <-time.After(10 * time.Second):
28
-			if err := clnt.Signal(containerID, int(syscall.SIGKILL)); err != nil {
29
-				logrus.Errorf("error sending sigkill to %v: %v", containerID, err)
30
-			}
31
-			select {
32
-			case <-time.After(2 * time.Second):
33
-			case <-w.wait():
34
-				return nil
35
-			}
36
-		case <-w.wait():
37
-			return nil
38
-		}
39
-	}
40
-	return clnt.setExited(containerID)
41
-}