Browse code

Fix Put without Get in devicemapper

Signed-off-by: Liu Hua <sdu.liu@huawei.com>

Liu Hua authored on 2015/12/03 23:22:25
Showing 2 changed files
... ...
@@ -2115,7 +2115,7 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
2115 2115
 }
2116 2116
 
2117 2117
 // UnmountDevice unmounts the device and removes it from hash.
2118
-func (devices *DeviceSet) UnmountDevice(hash string) error {
2118
+func (devices *DeviceSet) UnmountDevice(hash, mountPath string) error {
2119 2119
 	logrus.Debugf("[devmapper] UnmountDevice(hash=%s)", hash)
2120 2120
 	defer logrus.Debugf("[devmapper] UnmountDevice(hash=%s) END", hash)
2121 2121
 
... ...
@@ -2130,17 +2130,22 @@ func (devices *DeviceSet) UnmountDevice(hash string) error {
2130 2130
 	devices.Lock()
2131 2131
 	defer devices.Unlock()
2132 2132
 
2133
-	if info.mountCount == 0 {
2134
-		return fmt.Errorf("UnmountDevice: device not-mounted id %s", hash)
2135
-	}
2133
+	// If there are running containers when daemon crashes, during daemon
2134
+	// restarting, it will kill running contaienrs and will finally call
2135
+	// Put() without calling Get(). So info.MountCount may become negative.
2136
+	// if info.mountCount goes negative, we do the unmount and assign
2137
+	// it to 0.
2136 2138
 
2137 2139
 	info.mountCount--
2138 2140
 	if info.mountCount > 0 {
2139 2141
 		return nil
2142
+	} else if info.mountCount < 0 {
2143
+		logrus.Warnf("[devmapper] Mount count of device went negative. Put() called without matching Get(). Resetting count to 0")
2144
+		info.mountCount = 0
2140 2145
 	}
2141 2146
 
2142
-	logrus.Debugf("[devmapper] Unmount(%s)", info.mountPath)
2143
-	if err := syscall.Unmount(info.mountPath, syscall.MNT_DETACH); err != nil {
2147
+	logrus.Debugf("[devmapper] Unmount(%s)", mountPath)
2148
+	if err := syscall.Unmount(mountPath, syscall.MNT_DETACH); err != nil {
2144 2149
 		return err
2145 2150
 	}
2146 2151
 	logrus.Debugf("[devmapper] Unmount done")
... ...
@@ -186,7 +186,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
186 186
 
187 187
 	rootFs := path.Join(mp, "rootfs")
188 188
 	if err := idtools.MkdirAllAs(rootFs, 0755, uid, gid); err != nil && !os.IsExist(err) {
189
-		d.DeviceSet.UnmountDevice(id)
189
+		d.DeviceSet.UnmountDevice(id, mp)
190 190
 		return "", err
191 191
 	}
192 192
 
... ...
@@ -195,7 +195,7 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
195 195
 		// Create an "id" file with the container/image id in it to help reconscruct this in case
196 196
 		// of later problems
197 197
 		if err := ioutil.WriteFile(idFile, []byte(id), 0600); err != nil {
198
-			d.DeviceSet.UnmountDevice(id)
198
+			d.DeviceSet.UnmountDevice(id, mp)
199 199
 			return "", err
200 200
 		}
201 201
 	}
... ...
@@ -205,7 +205,8 @@ func (d *Driver) Get(id, mountLabel string) (string, error) {
205 205
 
206 206
 // Put unmounts a device and removes it.
207 207
 func (d *Driver) Put(id string) error {
208
-	err := d.DeviceSet.UnmountDevice(id)
208
+	mp := path.Join(d.home, "mnt", id)
209
+	err := d.DeviceSet.UnmountDevice(id, mp)
209 210
 	if err != nil {
210 211
 		logrus.Errorf("Error unmounting device %s: %s", id, err)
211 212
 	}