|
@@ -14,6 +14,7 @@ import (
|
|
"strconv"
|
|
"strconv"
|
|
"strings"
|
|
"strings"
|
|
"sync"
|
|
"sync"
|
|
|
|
+ "syscall"
|
|
"time"
|
|
"time"
|
|
)
|
|
)
|
|
|
|
|
|
@@ -677,6 +678,12 @@ func (devices *DeviceSet) deactivateDevice(hash string) error {
|
|
utils.Debugf("[devmapper] deactivateDevice(%s)", hash)
|
|
utils.Debugf("[devmapper] deactivateDevice(%s)", hash)
|
|
defer utils.Debugf("[devmapper] deactivateDevice END")
|
|
defer utils.Debugf("[devmapper] deactivateDevice END")
|
|
|
|
|
|
|
|
+ // Wait for the unmount to be effective,
|
|
|
|
+ // by watching the value of Info.OpenCount for the device
|
|
|
|
+ if err := devices.waitClose(hash); err != nil {
|
|
|
|
+ utils.Errorf("Warning: error waiting for device %s to close: %s\n", hash, err)
|
|
|
|
+ }
|
|
|
|
+
|
|
info := devices.Devices[hash]
|
|
info := devices.Devices[hash]
|
|
if info == nil {
|
|
if info == nil {
|
|
return fmt.Errorf("Unknown device %s", hash)
|
|
return fmt.Errorf("Unknown device %s", hash)
|
|
@@ -799,24 +806,18 @@ func (devices *DeviceSet) Shutdown() error {
|
|
for _, info := range devices.Devices {
|
|
for _, info := range devices.Devices {
|
|
info.lock.Lock()
|
|
info.lock.Lock()
|
|
if info.mountCount > 0 {
|
|
if info.mountCount > 0 {
|
|
- if err := sysUnmount(info.mountPath, 0); err != nil {
|
|
|
|
|
|
+ // We use MNT_DETACH here in case it is still busy in some running
|
|
|
|
+ // container. This means it'll go away from the global scope directly,
|
|
|
|
+ // and the device will be released when that container dies.
|
|
|
|
+ if err := sysUnmount(info.mountPath, syscall.MNT_DETACH); err != nil {
|
|
utils.Debugf("Shutdown unmounting %s, error: %s\n", info.mountPath, err)
|
|
utils.Debugf("Shutdown unmounting %s, error: %s\n", info.mountPath, err)
|
|
}
|
|
}
|
|
- }
|
|
|
|
- info.lock.Unlock()
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- for _, d := range devices.Devices {
|
|
|
|
- d.lock.Lock()
|
|
|
|
|
|
|
|
- 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 {
|
|
|
|
- utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
|
|
|
|
|
|
+ if err := devices.deactivateDevice(info.Hash); err != nil {
|
|
|
|
+ utils.Debugf("Shutdown deactivate %s , error: %s\n", info.Hash, err)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- d.lock.Unlock()
|
|
|
|
|
|
+ info.lock.Unlock()
|
|
}
|
|
}
|
|
|
|
|
|
if err := devices.deactivatePool(); err != nil {
|
|
if err := devices.deactivatePool(); err != nil {
|
|
@@ -920,14 +921,11 @@ func (devices *DeviceSet) UnmountDevice(hash string, mode UnmountMode) error {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
utils.Debugf("[devmapper] Unmount done")
|
|
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 {
|
|
|
|
|
|
+
|
|
|
|
+ if err := devices.deactivateDevice(hash); err != nil {
|
|
return err
|
|
return err
|
|
}
|
|
}
|
|
|
|
|
|
- devices.deactivateDevice(hash)
|
|
|
|
-
|
|
|
|
info.mountPath = ""
|
|
info.mountPath = ""
|
|
|
|
|
|
return nil
|
|
return nil
|