Browse Source

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

Solomon Hykes 11 years ago
parent
commit
1711de4b09
1 changed files with 36 additions and 0 deletions
  1. 36 0
      devmapper/deviceset_devmapper.go

+ 36 - 0
devmapper/deviceset_devmapper.go

@@ -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