diff options
| author | Tonis Tiigi <tonistiigi@gmail.com> | 2016-03-23 00:33:02 -0700 |
|---|---|---|
| committer | Tonis Tiigi <tonistiigi@gmail.com> | 2016-03-23 00:33:02 -0700 |
| commit | e91de9fb9d175541acc95834de486d33feef552a (patch) | |
| tree | 610bab6174675f30408c87644e864f1c58bce10c /daemon/graphdriver/devmapper | |
| parent | f668e36652e26f92c0f1a7fa3f648e5ed444b68e (diff) | |
| download | docker-e91de9fb9d175541acc95834de486d33feef552a.tar.gz | |
Revert "Move layer mount refcounts to mountedLayer"
This reverts commit 563d0711f83952e561a0d7d5c48fef9810b4f010.
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Diffstat (limited to 'daemon/graphdriver/devmapper')
| -rw-r--r-- | daemon/graphdriver/devmapper/deviceset.go | 84 | ||||
| -rw-r--r-- | daemon/graphdriver/devmapper/driver.go | 2 |
2 files changed, 55 insertions, 31 deletions
diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index cb3bf742a0..71c214d5d8 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -69,6 +69,9 @@ type devInfo struct { Deleted bool `json:"deleted"` devices *DeviceSet + mountCount int + mountPath string + // The global DeviceSet lock guarantees that we serialize all // the calls to libdevmapper (which is not threadsafe), but we // sometimes release that lock while sleeping. In that case @@ -1988,6 +1991,13 @@ func (devices *DeviceSet) DeleteDevice(hash string, syncDelete bool) error { devices.Lock() defer devices.Unlock() + // If mountcount is not zero, that means devices is still in use + // or has not been Put() properly. Fail device deletion. + + if info.mountCount != 0 { + return fmt.Errorf("devmapper: Can't delete device %v as it is still mounted. mntCount=%v", info.Hash, info.mountCount) + } + return devices.deleteDevice(info, syncDelete) } @@ -2106,11 +2116,13 @@ func (devices *DeviceSet) cancelDeferredRemoval(info *devInfo) error { } // Shutdown shuts down the device by unmounting the root. -func (devices *DeviceSet) Shutdown(home string) error { +func (devices *DeviceSet) Shutdown() error { logrus.Debugf("devmapper: [deviceset %s] Shutdown()", devices.devicePrefix) logrus.Debugf("devmapper: Shutting down DeviceSet: %s", devices.root) defer logrus.Debugf("devmapper: [deviceset %s] Shutdown() END", devices.devicePrefix) + var devs []*devInfo + // Stop deletion worker. This should start delivering new events to // ticker channel. That means no new instance of cleanupDeletedDevice() // will run after this call. If one instance is already running at @@ -2127,46 +2139,30 @@ func (devices *DeviceSet) Shutdown(home string) error { // metadata. Hence save this early before trying to deactivate devices. devices.saveDeviceSetMetaData() - // ignore the error since it's just a best effort to not try to unmount something that's mounted - mounts, _ := mount.GetMounts() - mounted := make(map[string]bool, len(mounts)) - for _, mnt := range mounts { - mounted[mnt.Mountpoint] = true + for _, info := range devices.Devices { + devs = append(devs, info) } + devices.Unlock() - if err := filepath.Walk(path.Join(home, "mnt"), func(p string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() { - return nil - } - - if mounted[p] { + for _, info := range devs { + info.lock.Lock() + if info.mountCount > 0 { // We use MNT_DETACH here in case it is still busy in some running // container. This means it'll go away from the global scope directly, // and the device will be released when that container dies. - if err := syscall.Unmount(p, syscall.MNT_DETACH); err != nil { - logrus.Debugf("devmapper: Shutdown unmounting %s, error: %s", p, err) + if err := syscall.Unmount(info.mountPath, syscall.MNT_DETACH); err != nil { + logrus.Debugf("devmapper: Shutdown unmounting %s, error: %s", info.mountPath, err) } - } - if devInfo, err := devices.lookupDevice(path.Base(p)); err != nil { - logrus.Debugf("devmapper: Shutdown lookup device %s, error: %s", path.Base(p), err) - } else { - if err := devices.deactivateDevice(devInfo); err != nil { - logrus.Debugf("devmapper: Shutdown deactivate %s , error: %s", devInfo.Hash, err) + devices.Lock() + if err := devices.deactivateDevice(info); err != nil { + logrus.Debugf("devmapper: Shutdown deactivate %s , error: %s", info.Hash, err) } + devices.Unlock() } - - return nil - }); err != nil && !os.IsNotExist(err) { - devices.Unlock() - return err + info.lock.Unlock() } - devices.Unlock() - info, _ := devices.lookupDeviceWithLock("") if info != nil { info.lock.Lock() @@ -2206,6 +2202,15 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { devices.Lock() defer devices.Unlock() + if info.mountCount > 0 { + if path != info.mountPath { + return fmt.Errorf("devmapper: Trying to mount devmapper device in multiple places (%s, %s)", info.mountPath, path) + } + + info.mountCount++ + return nil + } + if err := devices.activateDeviceIfNeeded(info, false); err != nil { return fmt.Errorf("devmapper: Error activating devmapper device for '%s': %s", hash, err) } @@ -2229,6 +2234,9 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { return fmt.Errorf("devmapper: Error mounting '%s' on '%s': %s", info.DevName(), path, err) } + info.mountCount = 1 + info.mountPath = path + return nil } @@ -2248,6 +2256,20 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { devices.Lock() defer devices.Unlock() + // If there are running containers when daemon crashes, during daemon + // restarting, it will kill running containers and will finally call + // Put() without calling Get(). So info.MountCount may become negative. + // if info.mountCount goes negative, we do the unmount and assign + // it to 0. + + info.mountCount-- + if info.mountCount > 0 { + return nil + } else if info.mountCount < 0 { + logrus.Warnf("devmapper: Mount count of device went negative. Put() called without matching Get(). Resetting count to 0") + info.mountCount = 0 + } + logrus.Debugf("devmapper: Unmount(%s)", mountPath) if err := syscall.Unmount(mountPath, syscall.MNT_DETACH); err != nil { return err @@ -2258,6 +2280,8 @@ func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { return err } + info.mountPath = "" + return nil } diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 7de6907c80..c03a7730ed 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -108,7 +108,7 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) { // Cleanup unmounts a device. func (d *Driver) Cleanup() error { - err := d.DeviceSet.Shutdown(d.home) + err := d.DeviceSet.Shutdown() if err2 := mount.Unmount(d.home); err == nil { err = err2 |
