devmapper: wait for devices to be effectively unmounted before removing them

This commit is contained in:
Solomon Hykes 2013-10-16 23:06:07 +00:00
parent 11d695a297
commit 1711de4b09
1 changed files with 36 additions and 0 deletions

View File

@ -1,6 +1,7 @@
package devmapper package devmapper
import ( import (
"time"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/dotcloud/docker/utils" "github.com/dotcloud/docker/utils"
@ -546,6 +547,32 @@ func (devices *DeviceSetDM) deactivateDevice(hash string) error {
return nil return nil
} }
// waitClose blocks until either:
// a) the device registered at <device_set_prefix>-<hash> is closed,
// or b) the 1 second timeout expires.
func (devices *DeviceSetDM) waitClose(hash string) error {
devname, err := devices.byHash(hash)
if err != nil {
return err
}
i := 0
for ; i<1000; i+=1 {
devinfo, err := getInfo(devname)
if err != nil {
return err
}
utils.Debugf("Waiting for unmount of %s: opencount=%d", devname, devinfo.OpenCount)
if devinfo.OpenCount == 0 {
break
}
time.Sleep(1 * time.Millisecond)
}
if i == 1000 {
return fmt.Errorf("Timeout while waiting for device %s to close", devname)
}
return nil
}
func (devices *DeviceSetDM) DeactivateDevice(hash string) error { func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
devices.Lock() devices.Lock()
defer devices.Unlock() defer devices.Unlock()
@ -578,6 +605,9 @@ func (devices *DeviceSetDM) Shutdown() error {
} }
for _, d := range devices.Devices { for _, d := range devices.Devices {
if err := devices.waitClose(d.Hash); err != nil {
utils.Errorf("Warning: error waiting for device %s to unmount: %s\n", d.Hash, err)
}
if err := devices.deactivateDevice(d.Hash); err != nil { if err := devices.deactivateDevice(d.Hash); err != nil {
utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err) utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
} }
@ -632,6 +662,12 @@ func (devices *DeviceSetDM) UnmountDevice(hash, path string, deactivate bool) er
utils.Debugf("\n--->Err: %s\n", err) utils.Debugf("\n--->Err: %s\n", err)
return err return err
} }
utils.Debugf("[devmapper] Unmount done")
// Wait for the unmount to be effective,
// by watching the value of Info.OpenCount for the device
if err := devices.waitClose(hash); err != nil {
return err
}
if count := devices.activeMounts[path]; count > 1 { if count := devices.activeMounts[path]; count > 1 {
devices.activeMounts[path] = count - 1 devices.activeMounts[path] = count - 1