瀏覽代碼

devmapper: Cancel deferred deactivation if device is reactivated

If device is being reactivated before it could go away and deferred 
deactivation is scheduled on it, cancel it.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Vivek Goyal 10 年之前
父節點
當前提交
ddc8acebec
共有 1 個文件被更改,包括 45 次插入0 次删除
  1. 45 0
      daemon/graphdriver/devmapper/deviceset.go

+ 45 - 0
daemon/graphdriver/devmapper/deviceset.go

@@ -438,6 +438,12 @@ func (devices *DeviceSet) registerDevice(id int, hash string, size uint64, trans
 func (devices *DeviceSet) activateDeviceIfNeeded(info *DevInfo) error {
 func (devices *DeviceSet) activateDeviceIfNeeded(info *DevInfo) error {
 	logrus.Debugf("activateDeviceIfNeeded(%v)", info.Hash)
 	logrus.Debugf("activateDeviceIfNeeded(%v)", info.Hash)
 
 
+	// Make sure deferred removal on device is canceled, if one was
+	// scheduled.
+	if err := devices.cancelDeferredRemoval(info); err != nil {
+		return fmt.Errorf("Deivce Deferred Removal Cancellation Failed: %s", err)
+	}
+
 	if devinfo, _ := devicemapper.GetInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
 	if devinfo, _ := devicemapper.GetInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
 		return nil
 		return nil
 	}
 	}
@@ -1331,6 +1337,45 @@ func (devices *DeviceSet) removeDevice(devname string) error {
 	return err
 	return err
 }
 }
 
 
+func (devices *DeviceSet) cancelDeferredRemoval(info *DevInfo) error {
+	if !devices.deferredRemove {
+		return nil
+	}
+
+	logrus.Debugf("[devmapper] cancelDeferredRemoval START(%s)", info.Name())
+	defer logrus.Debugf("[devmapper] cancelDeferredRemoval END(%s)", info.Name)
+
+	devinfo, err := devicemapper.GetInfoWithDeferred(info.Name())
+
+	if devinfo != nil && devinfo.DeferredRemove == 0 {
+		return nil
+	}
+
+	// Cancel deferred remove
+	for i := 0; i < 100; i++ {
+		err = devicemapper.CancelDeferredRemove(info.Name())
+		if err == nil {
+			break
+		}
+
+		if err == devicemapper.ErrEnxio {
+			// Device is probably already gone. Return success.
+			return nil
+		}
+
+		if err != devicemapper.ErrBusy {
+			return err
+		}
+
+		// If we see EBUSY it may be a transient error,
+		// sleep a bit a retry a few times.
+		devices.Unlock()
+		time.Sleep(100 * time.Millisecond)
+		devices.Lock()
+	}
+	return err
+}
+
 func (devices *DeviceSet) Shutdown() error {
 func (devices *DeviceSet) Shutdown() error {
 	logrus.Debugf("[deviceset %s] Shutdown()", devices.devicePrefix)
 	logrus.Debugf("[deviceset %s] Shutdown()", devices.devicePrefix)
 	logrus.Debugf("[devmapper] Shutting down DeviceSet: %s", devices.root)
 	logrus.Debugf("[devmapper] Shutting down DeviceSet: %s", devices.root)