Skip to content

Automatically set may_detach_mounts=1 on startup#34886

Merged
yongtang merged 1 commit intomoby:masterfrom
cpuguy83:may_detach_mount
Sep 20, 2017
Merged

Automatically set may_detach_mounts=1 on startup#34886
yongtang merged 1 commit intomoby:masterfrom
cpuguy83:may_detach_mount

Conversation

@cpuguy83
Copy link
Copy Markdown
Member

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.

@runcom
Copy link
Copy Markdown
Member

runcom commented Sep 18, 2017

Looks good, ping @rhvgoyal

@rhvgoyal
Copy link
Copy Markdown
Contributor

LGTM.

We already do this with the help of sysctl interface. So over a boot, all the sysctl settings are applied and this is already enabled by the time docker runs.

Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor nits, but LGTM otherwise :)

Comment thread daemon/daemon_unix.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh! typo: s/may_deatch_mounts/may_detach_mounts/

Comment thread daemon/daemon_unix.go Outdated
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's no need to use %q here, because "1" is hardcoded

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it quotes it, which is pretty ugly to do otherwise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backticks for the string?

`Permission denied writing "1" to ....`

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 <[email protected]>
Copy link
Copy Markdown
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kolyshkin
Copy link
Copy Markdown
Contributor

kolyshkin commented Sep 21, 2017

Wonderful! I was just going to work on a similar PR, but for the devmapper graph driver only (as its "deferred deletion" feature only works in case fs.may_detach_mounts=1). I did not realize it might be helpful in non-devmapper case, too. This patch will also help in case of autodetection whether deferred deletion is working or not (see mbentley/docker-devicemapper-setup#4).

The alternative approach is to add a /usr/lib/sysctl.d/90-docker.conf file to docker rpm spec, containing fs.may_detach_mounts=1, and adding a kludge to the .spec so that the setting is also applied upon rpm installation. This would be cleaner (and this is what Red Hat's runc rpm does) -- the only downside is anyone who's not installing from an rpm would not get it.

Yet another alternative is something like:

// -q: not display the value set, -e: ignore non-existent key
err := exec.Command("sysctl", "-q", "-e", "fs.may_detach_mounts=1").Run()
...

While exec sn ugly in general, this is only done once upon daemon (re)start so it's OK.

@thaJeztah
Copy link
Copy Markdown
Member

Yet another alternative is something like:

I do like the alternative approach (cleaner); would the permissions denied error still be properly returned with that code?

@kolyshkin
Copy link
Copy Markdown
Contributor

I do like the alternative approach (cleaner); would the permissions denied error
still be properly returned with that code?

Well, what we'll get is an exit code (most probably a generic 1) and a text from stderr (which we can parse for "permission denied" but it's a slippery slope as the locale might change that). I suggest treating any error, not just EPERM, in the same way, like:

s := "fs.may_detach_mounts=1"
// -q: not display the value set, -e: ignore non-existent key
err := exec.Command("sysctl", "-q", "-e", s).Run()
// ignore the error if the daemon is inside userns
if err != nil && !rsystem.RunningInUserNS() {
	logrus.Warnf("Error setting %s: %v", s, err)
}

Or maybe even not try setting this at all if we're in userns:

// do not try to set sysctls from inside userns
if !rsystem.RunningInUserNS() {
	s := "fs.may_detach_mounts=1"
	// -q: not display the value set, -e: ignore non-existent key
	if err := exec.Command("sysctl", "-q", "-e", s).Run(); err != nil {
		logrus.Warnf("Error setting %s sysctl: %v", s, err)
}

@thaJeztah
Copy link
Copy Markdown
Member

(If @cpuguy83 agrees) feel free to open a PR with that change

@cpuguy83
Copy link
Copy Markdown
Member Author

Why use exec here?

@cpuguy83
Copy link
Copy Markdown
Member Author

I'd be fine with setting this in the systemd conf, however that's really a packaging issue which we don't really deal with in this repo (though there are some init scripts in contrib).

@kolyshkin
Copy link
Copy Markdown
Contributor

kolyshkin commented Sep 21, 2017

Why use exec here?

As I said earlier, While exec sn ugly in general, this is only done once upon daemon (re)start so it's OK.

The benefits I see are:

  • using more standard interface
  • less code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants