mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
devmapper: prevent libdevmapper from deleting device symlinks in RemoveDeviceDeferred
if there is no cookie set in dm task, or flag DM_UDEV_DISABLE_LIBRARY_FALLBACK is cleared for a DM_DEV_REMOVE task, libdevmapper will fallback to clean up the symlink under /dev/mapper by itself, no matter the device removal is executed immediately or deferred by the kernel.In some cases, the removal is deferred by the kernel, while the symlink is deleted directly by libdevmapper, when docker tries to activate the device again, the deferred removal will be canceld, but the symlink will not show up again, so docker's attempt to mount the device by the symlink will fail, and it will eventually leads to a `docker start/diff` error. Fixes #24671 Signed-off-by: Ji.Zhilong <zhilongji@gmail.com>
This commit is contained in:
parent
b97f985054
commit
5e505d101f
1 changed files with 21 additions and 0 deletions
|
@ -358,6 +358,27 @@ func RemoveDeviceDeferred(name string) error {
|
|||
return ErrTaskDeferredRemove
|
||||
}
|
||||
|
||||
// set a task cookie and disable library fallback, or else libdevmapper will
|
||||
// disable udev dm rules and delete the symlink under /dev/mapper by itself,
|
||||
// even if the removal is deferred by the kernel.
|
||||
var cookie uint
|
||||
var flags uint16
|
||||
flags = DmUdevDisableLibraryFallback
|
||||
if err := task.setCookie(&cookie, flags); err != nil {
|
||||
return fmt.Errorf("devicemapper: Can not set cookie: %s", err)
|
||||
}
|
||||
|
||||
// libdevmapper and udev relies on System V semaphore for synchronization,
|
||||
// semaphores created in `task.setCookie` will be cleaned up in `UdevWait`.
|
||||
// So these two function call must come in pairs, otherwise semaphores will
|
||||
// be leaked, and the limit of number of semaphores defined in `/proc/sys/kernel/sem`
|
||||
// will be reached, which will eventually make all follwing calls to 'task.SetCookie'
|
||||
// fail.
|
||||
// this call will not wait for the deferred removal's final executing, since no
|
||||
// udev event will be generated, and the semaphore's value will not be incremented
|
||||
// by udev, what UdevWait is just cleaning up the semaphore.
|
||||
defer UdevWait(&cookie)
|
||||
|
||||
if err = task.run(); err != nil {
|
||||
return fmt.Errorf("devicemapper: Error running RemoveDeviceDeferred %s", err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue