Browse Source

Merge pull request #12033 from rhvgoyal/devmapper-cleanup

Devmapper Graph Driver Misc cleanup
Vincent Batts 10 years ago
parent
commit
86d66d6273
2 changed files with 34 additions and 96 deletions
  1. 27 87
      daemon/graphdriver/devmapper/deviceset.go
  2. 7 9
      pkg/devicemapper/devmapper.go

+ 27 - 87
daemon/graphdriver/devmapper/deviceset.go

@@ -33,6 +33,10 @@ var (
 	DefaultThinpBlockSize       uint32 = 128      // 64K = 128 512b sectors
 	DefaultThinpBlockSize       uint32 = 128      // 64K = 128 512b sectors
 	MaxDeviceId                 int    = 0xffffff // 24 bit, pool limit
 	MaxDeviceId                 int    = 0xffffff // 24 bit, pool limit
 	DeviceIdMapSz               int    = (MaxDeviceId + 1) / 8
 	DeviceIdMapSz               int    = (MaxDeviceId + 1) / 8
+	// We retry device removal so many a times that even error messages
+	// will fill up console during normal operation. So only log Fatal
+	// messages by default.
+	DMLogLevel int = devicemapper.LogLevelFatal
 )
 )
 
 
 const deviceSetMetaFile string = "deviceset-metadata"
 const deviceSetMetaFile string = "deviceset-metadata"
@@ -723,14 +727,22 @@ func setCloseOnExec(name string) {
 }
 }
 
 
 func (devices *DeviceSet) DMLog(level int, file string, line int, dmError int, message string) {
 func (devices *DeviceSet) DMLog(level int, file string, line int, dmError int, message string) {
-	if level >= devicemapper.LogLevelDebug {
-		// (vbatts) libdm debug is very verbose. If you're debugging libdm, you can
-		// comment out this check yourself
-		level = devicemapper.LogLevelInfo
+	// By default libdm sends us all the messages including debug ones.
+	// We need to filter out messages here and figure out which one
+	// should be printed.
+	if level > DMLogLevel {
+		return
 	}
 	}
 
 
 	// FIXME(vbatts) push this back into ./pkg/devicemapper/
 	// FIXME(vbatts) push this back into ./pkg/devicemapper/
-	logrus.Debugf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message)
+	if level <= devicemapper.LogLevelErr {
+		logrus.Errorf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message)
+	} else if level <= devicemapper.LogLevelInfo {
+		logrus.Infof("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message)
+	} else {
+		// FIXME(vbatts) push this back into ./pkg/devicemapper/
+		logrus.Debugf("libdevmapper(%d): %s:%d (%d) %s", level, file, line, dmError, message)
+	}
 }
 }
 
 
 func major(device uint64) uint64 {
 func major(device uint64) uint64 {
@@ -947,11 +959,6 @@ func (devices *DeviceSet) closeTransaction() error {
 }
 }
 
 
 func (devices *DeviceSet) initDevmapper(doInit bool) error {
 func (devices *DeviceSet) initDevmapper(doInit bool) error {
-	if os.Getenv("DEBUG") != "" {
-		devicemapper.LogInitVerbose(devicemapper.LogLevelDebug)
-	} else {
-		devicemapper.LogInitVerbose(devicemapper.LogLevelWarn)
-	}
 	// give ourselves to libdm as a log handler
 	// give ourselves to libdm as a log handler
 	devicemapper.LogInit(devices)
 	devicemapper.LogInit(devices)
 
 
@@ -1150,7 +1157,7 @@ func (devices *DeviceSet) deleteDevice(info *DevInfo) error {
 
 
 	devinfo, _ := devicemapper.GetInfo(info.Name())
 	devinfo, _ := devicemapper.GetInfo(info.Name())
 	if devinfo != nil && devinfo.Exists != 0 {
 	if devinfo != nil && devinfo.Exists != 0 {
-		if err := devices.removeDeviceAndWait(info.Name()); err != nil {
+		if err := devices.removeDevice(info.Name()); err != nil {
 			logrus.Debugf("Error removing device: %s", err)
 			logrus.Debugf("Error removing device: %s", err)
 			return err
 			return err
 		}
 		}
@@ -1218,18 +1225,12 @@ func (devices *DeviceSet) deactivateDevice(info *DevInfo) error {
 	logrus.Debugf("[devmapper] deactivateDevice(%s)", info.Hash)
 	logrus.Debugf("[devmapper] deactivateDevice(%s)", info.Hash)
 	defer logrus.Debugf("[devmapper] deactivateDevice END(%s)", info.Hash)
 	defer logrus.Debugf("[devmapper] deactivateDevice END(%s)", info.Hash)
 
 
-	// Wait for the unmount to be effective,
-	// by watching the value of Info.OpenCount for the device
-	if err := devices.waitClose(info); err != nil {
-		logrus.Errorf("Error waiting for device %s to close: %s", info.Hash, err)
-	}
-
 	devinfo, err := devicemapper.GetInfo(info.Name())
 	devinfo, err := devicemapper.GetInfo(info.Name())
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 	if devinfo.Exists != 0 {
 	if devinfo.Exists != 0 {
-		if err := devices.removeDeviceAndWait(info.Name()); err != nil {
+		if err := devices.removeDevice(info.Name()); err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
@@ -1237,12 +1238,14 @@ func (devices *DeviceSet) deactivateDevice(info *DevInfo) error {
 	return nil
 	return nil
 }
 }
 
 
-// Issues the underlying dm remove operation and then waits
-// for it to finish.
-func (devices *DeviceSet) removeDeviceAndWait(devname string) error {
+// Issues the underlying dm remove operation.
+func (devices *DeviceSet) removeDevice(devname string) error {
 	var err error
 	var err error
 
 
-	for i := 0; i < 1000; i++ {
+	logrus.Debugf("[devmapper] removeDevice START(%s)", devname)
+	defer logrus.Debugf("[devmapper] removeDevice END(%s)", devname)
+
+	for i := 0; i < 200; i++ {
 		err = devicemapper.RemoveDevice(devname)
 		err = devicemapper.RemoveDevice(devname)
 		if err == nil {
 		if err == nil {
 			break
 			break
@@ -1254,74 +1257,11 @@ func (devices *DeviceSet) removeDeviceAndWait(devname string) error {
 		// If we see EBUSY it may be a transient error,
 		// If we see EBUSY it may be a transient error,
 		// sleep a bit a retry a few times.
 		// sleep a bit a retry a few times.
 		devices.Unlock()
 		devices.Unlock()
-		time.Sleep(10 * time.Millisecond)
+		time.Sleep(100 * time.Millisecond)
 		devices.Lock()
 		devices.Lock()
 	}
 	}
-	if err != nil {
-		return err
-	}
 
 
-	if err := devices.waitRemove(devname); err != nil {
-		return err
-	}
-	return nil
-}
-
-// waitRemove blocks until either:
-// a) the device registered at <device_set_prefix>-<hash> is removed,
-// or b) the 10 second timeout expires.
-func (devices *DeviceSet) waitRemove(devname string) error {
-	logrus.Debugf("[deviceset %s] waitRemove(%s)", devices.devicePrefix, devname)
-	defer logrus.Debugf("[deviceset %s] waitRemove(%s) END", devices.devicePrefix, devname)
-	i := 0
-	for ; i < 1000; i++ {
-		devinfo, err := devicemapper.GetInfo(devname)
-		if err != nil {
-			// If there is an error we assume the device doesn't exist.
-			// The error might actually be something else, but we can't differentiate.
-			return nil
-		}
-		if i%100 == 0 {
-			logrus.Debugf("Waiting for removal of %s: exists=%d", devname, devinfo.Exists)
-		}
-		if devinfo.Exists == 0 {
-			break
-		}
-
-		devices.Unlock()
-		time.Sleep(10 * time.Millisecond)
-		devices.Lock()
-	}
-	if i == 1000 {
-		return fmt.Errorf("Timeout while waiting for device %s to be removed", devname)
-	}
-	return nil
-}
-
-// waitClose blocks until either:
-// a) the device registered at <device_set_prefix>-<hash> is closed,
-// or b) the 10 second timeout expires.
-func (devices *DeviceSet) waitClose(info *DevInfo) error {
-	i := 0
-	for ; i < 1000; i++ {
-		devinfo, err := devicemapper.GetInfo(info.Name())
-		if err != nil {
-			return err
-		}
-		if i%100 == 0 {
-			logrus.Debugf("Waiting for unmount of %s: opencount=%d", info.Hash, devinfo.OpenCount)
-		}
-		if devinfo.OpenCount == 0 {
-			break
-		}
-		devices.Unlock()
-		time.Sleep(10 * time.Millisecond)
-		devices.Lock()
-	}
-	if i == 1000 {
-		return fmt.Errorf("Timeout while waiting for device %s to close", info.Hash)
-	}
-	return nil
+	return err
 }
 }
 
 
 func (devices *DeviceSet) Shutdown() error {
 func (devices *DeviceSet) Shutdown() error {

+ 7 - 9
pkg/devicemapper/devmapper.go

@@ -284,9 +284,9 @@ func FindLoopDeviceFor(file *os.File) *os.File {
 	return nil
 	return nil
 }
 }
 
 
-func UdevWait(cookie uint) error {
-	if res := DmUdevWait(cookie); res != 1 {
-		logrus.Debugf("Failed to wait on udev cookie %d", cookie)
+func UdevWait(cookie *uint) error {
+	if res := DmUdevWait(*cookie); res != 1 {
+		logrus.Debugf("Failed to wait on udev cookie %d", *cookie)
 		return ErrUdevWait
 		return ErrUdevWait
 	}
 	}
 	return nil
 	return nil
@@ -349,8 +349,6 @@ func CookieSupported() bool {
 
 
 // Useful helper for cleanup
 // Useful helper for cleanup
 func RemoveDevice(name string) error {
 func RemoveDevice(name string) error {
-	logrus.Debugf("[devmapper] RemoveDevice START(%s)", name)
-	defer logrus.Debugf("[devmapper] RemoveDevice END(%s)", name)
 	task, err := TaskCreateNamed(DeviceRemove, name)
 	task, err := TaskCreateNamed(DeviceRemove, name)
 	if task == nil {
 	if task == nil {
 		return err
 		return err
@@ -360,7 +358,7 @@ func RemoveDevice(name string) error {
 	if err := task.SetCookie(&cookie, 0); err != nil {
 	if err := task.SetCookie(&cookie, 0); err != nil {
 		return fmt.Errorf("Can not set cookie: %s", err)
 		return fmt.Errorf("Can not set cookie: %s", err)
 	}
 	}
-	defer UdevWait(cookie)
+	defer UdevWait(&cookie)
 
 
 	dmSawBusy = false // reset before the task is run
 	dmSawBusy = false // reset before the task is run
 	if err = task.Run(); err != nil {
 	if err = task.Run(); err != nil {
@@ -427,7 +425,7 @@ func CreatePool(poolName string, dataFile, metadataFile *os.File, poolBlockSize
 	if err := task.SetCookie(&cookie, flags); err != nil {
 	if err := task.SetCookie(&cookie, flags); err != nil {
 		return fmt.Errorf("Can't set cookie %s", err)
 		return fmt.Errorf("Can't set cookie %s", err)
 	}
 	}
-	defer UdevWait(cookie)
+	defer UdevWait(&cookie)
 
 
 	if err := task.Run(); err != nil {
 	if err := task.Run(); err != nil {
 		return fmt.Errorf("Error running DeviceCreate (CreatePool) %s", err)
 		return fmt.Errorf("Error running DeviceCreate (CreatePool) %s", err)
@@ -558,7 +556,7 @@ func ResumeDevice(name string) error {
 	if err := task.SetCookie(&cookie, 0); err != nil {
 	if err := task.SetCookie(&cookie, 0); err != nil {
 		return fmt.Errorf("Can't set cookie %s", err)
 		return fmt.Errorf("Can't set cookie %s", err)
 	}
 	}
-	defer UdevWait(cookie)
+	defer UdevWait(&cookie)
 
 
 	if err := task.Run(); err != nil {
 	if err := task.Run(); err != nil {
 		return fmt.Errorf("Error running DeviceResume %s", err)
 		return fmt.Errorf("Error running DeviceResume %s", err)
@@ -634,7 +632,7 @@ func ActivateDevice(poolName string, name string, deviceId int, size uint64) err
 		return fmt.Errorf("Can't set cookie %s", err)
 		return fmt.Errorf("Can't set cookie %s", err)
 	}
 	}
 
 
-	defer UdevWait(cookie)
+	defer UdevWait(&cookie)
 
 
 	if err := task.Run(); err != nil {
 	if err := task.Run(); err != nil {
 		return fmt.Errorf("Error running DeviceCreate (ActivateDevice) %s", err)
 		return fmt.Errorf("Error running DeviceCreate (ActivateDevice) %s", err)