A lot of time device mapper devices leak across mount namespace which docker
does not know about and when docker tries to deactivate/delete device,
operation fails as device is open in some mount namespace.
Create a mechanism where one can defer the device deactivation/deletion
so that docker operation does not fail and device automatically goes
away when last reference to it is dropped.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
... | ... |
@@ -55,6 +55,7 @@ var ( |
55 | 55 |
ErrTaskGetDeps = errors.New("dm_task_get_deps failed") |
56 | 56 |
ErrTaskGetInfo = errors.New("dm_task_get_info failed") |
57 | 57 |
ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed") |
58 |
+ ErrTaskDeferredRemove = errors.New("dm_task_deferred_remove failed") |
|
58 | 59 |
ErrTaskSetCookie = errors.New("dm_task_set_cookie failed") |
59 | 60 |
ErrNilCookie = errors.New("cookie ptr can't be nil") |
60 | 61 |
ErrAttachLoopbackDevice = errors.New("loopback mounting failed") |
... | ... |
@@ -371,6 +372,25 @@ func RemoveDevice(name string) error { |
371 | 371 |
return nil |
372 | 372 |
} |
373 | 373 |
|
374 |
+func RemoveDeviceDeferred(name string) error { |
|
375 |
+ logrus.Debugf("[devmapper] RemoveDeviceDeferred START(%s)", name) |
|
376 |
+ defer logrus.Debugf("[devmapper] RemoveDeviceDeferred END(%s)", name) |
|
377 |
+ task, err := TaskCreateNamed(DeviceRemove, name) |
|
378 |
+ if task == nil { |
|
379 |
+ return err |
|
380 |
+ } |
|
381 |
+ |
|
382 |
+ if err := DmTaskDeferredRemove(task.unmanaged); err != 1 { |
|
383 |
+ return ErrTaskDeferredRemove |
|
384 |
+ } |
|
385 |
+ |
|
386 |
+ if err = task.Run(); err != nil { |
|
387 |
+ return fmt.Errorf("Error running RemoveDeviceDeferred %s", err) |
|
388 |
+ } |
|
389 |
+ |
|
390 |
+ return nil |
|
391 |
+} |
|
392 |
+ |
|
374 | 393 |
func GetBlockDeviceSize(file *os.File) (uint64, error) { |
375 | 394 |
size, err := ioctlBlkGetSize64(file.Fd()) |
376 | 395 |
if err != nil { |
118 | 119 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,15 @@ |
0 |
+// +build linux,!libdm_no_deferred_remove |
|
1 |
+ |
|
2 |
+package devicemapper |
|
3 |
+ |
|
4 |
+/* |
|
5 |
+#cgo LDFLAGS: -L. -ldevmapper |
|
6 |
+#include <libdevmapper.h> |
|
7 |
+*/ |
|
8 |
+import "C" |
|
9 |
+ |
|
10 |
+const LibraryDeferredRemovalSupport = true |
|
11 |
+ |
|
12 |
+func dmTaskDeferredRemoveFct(task *CDmTask) int { |
|
13 |
+ return int(C.dm_task_deferred_remove((*C.struct_dm_task)(task))) |
|
14 |
+} |