Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
| ... | ... |
@@ -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 |
-} |