diff --git a/daemon/graphdriver/devmapper/deviceset.go b/daemon/graphdriver/devmapper/deviceset.go index 4d355ab472..b7eb3206e0 100644 --- a/daemon/graphdriver/devmapper/deviceset.go +++ b/daemon/graphdriver/devmapper/deviceset.go @@ -2115,7 +2115,7 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error { } // UnmountDevice unmounts the device and removes it from hash. -func (devices *DeviceSet) UnmountDevice(hash string) error { +func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error { logrus.Debugf("[devmapper] UnmountDevice(hash=%s)", hash) defer logrus.Debugf("[devmapper] UnmountDevice(hash=%s) END", hash) @@ -2130,17 +2130,22 @@ func (devices *DeviceSet) UnmountDevice(hash string) error { devices.Lock() defer devices.Unlock() - if info.mountCount == 0 { - return fmt.Errorf("UnmountDevice: device not-mounted id %s", hash) - } + // If there are running containers when daemon crashes, during daemon + // restarting, it will kill running contaienrs 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)", info.mountPath) - if err := syscall.Unmount(info.mountPath, syscall.MNT_DETACH); err != nil { + logrus.Debugf("[devmapper] Unmount(%s)", mountPath) + if err := syscall.Unmount(mountPath, syscall.MNT_DETACH); err != nil { return err } logrus.Debugf("[devmapper] Unmount done") diff --git a/daemon/graphdriver/devmapper/driver.go b/daemon/graphdriver/devmapper/driver.go index 2330daef82..11b2809d75 100644 --- a/daemon/graphdriver/devmapper/driver.go +++ b/daemon/graphdriver/devmapper/driver.go @@ -186,7 +186,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) { rootFs := path.Join(mp, "rootfs") if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) { - d.DeviceSet.UnmountDevice(id) + d.DeviceSet.UnmountDevice(id, mp) return "", err } @@ -195,7 +195,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) { // Create an "id" file with the container/image id in it to help reconscruct this in case // of later problems if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil { - d.DeviceSet.UnmountDevice(id) + d.DeviceSet.UnmountDevice(id, mp) return "", err } } @@ -205,7 +205,8 @@ func (d *Driver) Get(id, mountLabel string) (string, error) { // Put unmounts a device and removes it. func (d *Driver) Put(id string) error { - err := d.DeviceSet.UnmountDevice(id) + mp := path.Join(d.home, "mnt", id) + err := d.DeviceSet.UnmountDevice(id, mp) if err != nil { logrus.Errorf("Error unmounting device %s: %s", id, err) }