Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Michael Crosby authored on 2016/05/03 07:44:20... | ... |
@@ -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 |
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 |
-} |