Merge pull request #12033 from rhvgoyal/devmapper-cleanup
Devmapper Graph Driver Misc cleanup
This commit is contained in:
commit
86d66d6273
|
@ -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 {
|
// By default libdm sends us all the messages including debug ones.
|
||||||
// (vbatts) libdm debug is very verbose. If you're debugging libdm, you can
|
// We need to filter out messages here and figure out which one
|
||||||
// comment out this check yourself
|
// should be printed.
|
||||||
level = devicemapper.LogLevelInfo
|
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
|
// Issues the underlying dm remove operation.
|
||||||
// for it to finish.
|
func (devices *DeviceSet) removeDevice(devname string) error {
|
||||||
func (devices *DeviceSet) removeDeviceAndWait(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 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (devices *DeviceSet) Shutdown() error {
|
func (devices *DeviceSet) Shutdown() error {
|
||||||
|
|
|
@ -284,9 +284,9 @@ func FindLoopDeviceFor(file *os.File) *os.File {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UdevWait(cookie uint) error {
|
func UdevWait(cookie *uint) error {
|
||||||
if res := DmUdevWait(cookie); res != 1 {
|
if res := DmUdevWait(*cookie); res != 1 {
|
||||||
logrus.Debugf("Failed to wait on udev cookie %d", cookie)
|
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)
|
||||||
|
|
Loading…
Reference in New Issue