mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #4504 from alexlarsson/devicemapper-waits
devmapper: Increase sleep times and unlock while sleeping
This commit is contained in:
commit
b55a79aa1c
1 changed files with 45 additions and 4 deletions
|
@ -39,6 +39,13 @@ type DevInfo struct {
|
||||||
// first get (since we need to mount to set up the device
|
// first get (since we need to mount to set up the device
|
||||||
// a bit first).
|
// a bit first).
|
||||||
floating bool `json:"-"`
|
floating bool `json:"-"`
|
||||||
|
|
||||||
|
// The global DeviceSet lock guarantees that we serialize all
|
||||||
|
// the calls to libdevmapper (which is not threadsafe), but we
|
||||||
|
// sometimes release that lock while sleeping. In that case
|
||||||
|
// this per-device lock is still held, protecting against
|
||||||
|
// other accesses to the device that we're doing the wait on.
|
||||||
|
lock sync.Mutex `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetaData struct {
|
type MetaData struct {
|
||||||
|
@ -47,7 +54,7 @@ type MetaData struct {
|
||||||
|
|
||||||
type DeviceSet struct {
|
type DeviceSet struct {
|
||||||
MetaData
|
MetaData
|
||||||
sync.Mutex
|
sync.Mutex // Protects Devices map and serializes calls into libdevmapper
|
||||||
root string
|
root string
|
||||||
devicePrefix string
|
devicePrefix string
|
||||||
TransactionId uint64
|
TransactionId uint64
|
||||||
|
@ -569,6 +576,9 @@ func (devices *DeviceSet) AddDevice(hash, baseHash string) error {
|
||||||
return fmt.Errorf("Error adding device for '%s': can't find device for parent '%s'", hash, baseHash)
|
return fmt.Errorf("Error adding device for '%s': can't find device for parent '%s'", hash, baseHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
baseInfo.lock.Lock()
|
||||||
|
defer baseInfo.lock.Unlock()
|
||||||
|
|
||||||
deviceId := devices.allocateDeviceId()
|
deviceId := devices.allocateDeviceId()
|
||||||
|
|
||||||
if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
|
if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
|
||||||
|
@ -636,6 +646,14 @@ func (devices *DeviceSet) DeleteDevice(hash string) error {
|
||||||
devices.Lock()
|
devices.Lock()
|
||||||
defer devices.Unlock()
|
defer devices.Unlock()
|
||||||
|
|
||||||
|
info := devices.Devices[hash]
|
||||||
|
if info == nil {
|
||||||
|
return fmt.Errorf("Unknown device %s", hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
info.lock.Lock()
|
||||||
|
defer info.lock.Unlock()
|
||||||
|
|
||||||
return devices.deleteDevice(hash)
|
return devices.deleteDevice(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,7 +701,7 @@ func (devices *DeviceSet) deactivateDevice(hash string) error {
|
||||||
func (devices *DeviceSet) removeDeviceAndWait(devname string) error {
|
func (devices *DeviceSet) removeDeviceAndWait(devname string) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
devices.sawBusy = false
|
devices.sawBusy = false
|
||||||
err = removeDevice(devname)
|
err = removeDevice(devname)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -695,7 +713,9 @@ 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.
|
||||||
time.Sleep(5 * time.Millisecond)
|
devices.Unlock()
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
devices.Lock()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -728,7 +748,9 @@ func (devices *DeviceSet) waitRemove(devname string) error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(1 * time.Millisecond)
|
devices.Unlock()
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
devices.Lock()
|
||||||
}
|
}
|
||||||
if i == 1000 {
|
if i == 1000 {
|
||||||
return fmt.Errorf("Timeout while waiting for device %s to be removed", devname)
|
return fmt.Errorf("Timeout while waiting for device %s to be removed", devname)
|
||||||
|
@ -773,20 +795,26 @@ func (devices *DeviceSet) Shutdown() error {
|
||||||
defer utils.Debugf("[deviceset %s] shutdown END", devices.devicePrefix)
|
defer utils.Debugf("[deviceset %s] shutdown END", devices.devicePrefix)
|
||||||
|
|
||||||
for _, info := range devices.Devices {
|
for _, info := range devices.Devices {
|
||||||
|
info.lock.Lock()
|
||||||
if info.mountCount > 0 {
|
if info.mountCount > 0 {
|
||||||
if err := sysUnmount(info.mountPath, 0); err != nil {
|
if err := sysUnmount(info.mountPath, 0); 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 {
|
for _, d := range devices.Devices {
|
||||||
|
d.lock.Lock()
|
||||||
|
|
||||||
if err := devices.waitClose(d.Hash); err != nil {
|
if err := devices.waitClose(d.Hash); err != nil {
|
||||||
utils.Errorf("Warning: error waiting for device %s to unmount: %s\n", d.Hash, err)
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := devices.deactivatePool(); err != nil {
|
if err := devices.deactivatePool(); err != nil {
|
||||||
|
@ -805,6 +833,9 @@ func (devices *DeviceSet) MountDevice(hash, path string) error {
|
||||||
return fmt.Errorf("Unknown device %s", hash)
|
return fmt.Errorf("Unknown device %s", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.lock.Lock()
|
||||||
|
defer info.lock.Unlock()
|
||||||
|
|
||||||
if info.mountCount > 0 {
|
if info.mountCount > 0 {
|
||||||
if path != info.mountPath {
|
if path != info.mountPath {
|
||||||
return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
|
return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
|
||||||
|
@ -851,6 +882,9 @@ func (devices *DeviceSet) UnmountDevice(hash string, mode UnmountMode) error {
|
||||||
return fmt.Errorf("UnmountDevice: no such device %s\n", hash)
|
return fmt.Errorf("UnmountDevice: no such device %s\n", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.lock.Lock()
|
||||||
|
defer info.lock.Unlock()
|
||||||
|
|
||||||
if mode == UnmountFloat {
|
if mode == UnmountFloat {
|
||||||
if info.floating {
|
if info.floating {
|
||||||
return fmt.Errorf("UnmountDevice: can't float floating reference %s\n", hash)
|
return fmt.Errorf("UnmountDevice: can't float floating reference %s\n", hash)
|
||||||
|
@ -920,6 +954,10 @@ func (devices *DeviceSet) HasActivatedDevice(hash string) bool {
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.lock.Lock()
|
||||||
|
defer info.lock.Unlock()
|
||||||
|
|
||||||
devinfo, _ := getInfo(info.Name())
|
devinfo, _ := getInfo(info.Name())
|
||||||
return devinfo != nil && devinfo.Exists != 0
|
return devinfo != nil && devinfo.Exists != 0
|
||||||
}
|
}
|
||||||
|
@ -974,6 +1012,9 @@ func (devices *DeviceSet) GetDeviceStatus(hash string) (*DevStatus, error) {
|
||||||
return nil, fmt.Errorf("No device %s", hash)
|
return nil, fmt.Errorf("No device %s", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.lock.Lock()
|
||||||
|
defer info.lock.Unlock()
|
||||||
|
|
||||||
status := &DevStatus{
|
status := &DevStatus{
|
||||||
DeviceId: info.DeviceId,
|
DeviceId: info.DeviceId,
|
||||||
Size: info.Size,
|
Size: info.Size,
|
||||||
|
|
Loading…
Add table
Reference in a new issue