From 0f16d9b90a348dcadb73fa46b9e2751e5bef0985 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Mon, 18 Sep 2017 09:26:34 -0400 Subject: [PATCH] Automatically set `may_detach_mounts=1` on startup This is kernel config available in RHEL7.4 based kernels that enables mountpoint removal where the mountpoint exists in other namespaces. In particular this is important for making this pattern work: ``` umount -l /some/path rm -r /some/path ``` Where `/some/path` exists in another mount namespace. Setting this value will prevent `device or resource busy` errors when attempting to the removal of `/some/path` in the example. This setting is the default, and non-configurable, on upstream kernels since 3.15. Signed-off-by: Brian Goff (cherry picked from commit 83c2152de503012195bd26069fd8fbd2dea4b32f) Signed-off-by: Sebastiaan van Stijn --- components/engine/daemon/daemon_unix.go | 34 ++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go index 0082706b6c..fdb0f0a2a5 100644 --- a/components/engine/daemon/daemon_unix.go +++ b/components/engine/daemon/daemon_unix.go @@ -1295,7 +1295,39 @@ func rootFSToAPIType(rootfs *image.RootFS) types.RootFS { // setupDaemonProcess sets various settings for the daemon's process func setupDaemonProcess(config *config.Config) error { // setup the daemons oom_score_adj - return setupOOMScoreAdj(config.OOMScoreAdjust) + if err := setupOOMScoreAdj(config.OOMScoreAdjust); err != nil { + return err + } + return setMayDetachMounts() +} + +// This is used to allow removal of mountpoints that may be mounted in other +// namespaces on RHEL based kernels starting from RHEL 7.4. +// Without this setting, removals on these RHEL based kernels may fail with +// "device or resource busy". +// This setting is not available in upstream kernels as it is not configurable, +// but has been in the upstream kernels since 3.15. +func setMayDetachMounts() error { + f, err := os.OpenFile("/proc/sys/fs/may_detach_mounts", os.O_WRONLY, 0) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return errors.Wrap(err, "error opening may_detach_mounts kernel config file") + } + defer f.Close() + + _, err = f.WriteString("1") + if os.IsPermission(err) { + // Setting may_detach_mounts does not work in an + // unprivileged container. Ignore the error, but log + // it if we appear not to be in that situation. + if !rsystem.RunningInUserNS() { + logrus.Debugf("Permission denied writing %q to /proc/sys/fs/may_detach_mounts", "1") + } + return nil + } + return err } func setupOOMScoreAdj(score int) error {