-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Fix "duplicate mount point" when --tmpfs /dev/shm is used #35467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1723486
to
bbfc7a3
Compare
LGTM |
The followup to this is to make a client use mount api for |
Trying some of the examples mentioned in #6758 (comment), the
I'm testing this inside the dev-container, so the |
Honoring the I will check it, too. |
Oh, right, I assumed this was rebased, let me try rebasing on master and see if it works |
The code in question looks up mounts two times: first by using HasMountFor(), and then directly by looking in container.MountPoints. There is no need to do it twice. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This is a fix to the following issue: $ docker run --tmpfs /dev/shm busybox sh docker: Error response from daemon: linux mounts: Duplicate mount point '/dev/shm'. In current code (daemon.createSpec()), tmpfs mount from --tmpfs is added to list of mounts (`ms`), when the mount from IpcMounts() is added. While IpcMounts() is checking for existing mounts first, it does that by using container.HasMountFor() function which only checks container.Mounts but not container.Tmpfs. Ultimately, the solution is to get rid of container.Tmpfs (moving its data to container.Mounts). Current workaround is to add checking of container.Tmpfs into container.HasMountFor(). A unit test case is included. Unfortunately we can't call daemon.createSpec() from a unit test, as the code relies a lot on various daemon structures to be initialized properly, and it is hard to achieve. Therefore, we minimally mimick the code flow of daemon.createSpec() -- barely enough to reproduce the issue. moby#35455 Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
I have rebased it and ran some manual tests:
Note the last one is interesting -- if tmpfs size is not set, the in-kernel default is used (half the RAM as per kernel Documentation/filesystems/tmpfs.txt). |
Thanks! That was indeed the reason my earlier testing didn't work 😊
Yes, also noticed that while testing; I think we should apply the default size if no size was provided, because even in the most minimal case (e.g., just adding wdyt? |
Hm, there's actually some prior discussion on this for tmpfs (in general, so not So, hm, I don't know what the behaviour should be ping @justincormack as well 😄 |
I'm not sure what would be the right thing to do. The default size we have is for the default Anyway, by looking at git commits I see there was one that added the default size:
That last PR refers to issue #23394. The issue is with Anyway, my understanding is, some people rely on Our options here are in abundance:
Based on my experience with OpenVZ, having restrictive options by default (as in 2 and 3 above) is good and bad at the same time. Being restrictive by default is good because:
Being restrictive by default is bad because:
Other source of wisdom is UNIX; unfortunately it sends us mixed signals, from Unix is user-friendly — it's just choosy about who its friends are (applicable to the case, that would mean "be restrictive by default and let users figure out all the knobs and dials"), to UNIX gives its users many ways to shoot themselves in a foot (applicable to this case, that'd mean "don't impose any restrictions"). Another way to look at it is "what do we usually do in such cases". Historically, Docker imposes no limits by default (say, RAM and disk space is not limited by default -- although perhaps it happened that way because there were no means to control such resources at that time). This is probably what users are expecting. To sum it up: while personally I'd prefer limiting, I think leaving it as is would be more appropriate. Option 4, limit it to half a RAM (of container, if configured) is also a sensible option, but I guess it is better to be done in the kernel, which means it's the same as option 1. |
Thanks for summarising the options, @kolyshkin! I was briefly discussing this with @justincormack yesterday, and although we set defaults for $ docker run --rm --tmpfs /foo busybox sh -c 'mount | grep shm'
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k) $ docker run --rm --tmpfs /foo busybox sh -c 'mount | grep foo'
tmpfs on /foo type tmpfs (rw,nosuid,nodev,noexec,relatime) So, even though using Based on the above, I consider the current implementation to be correct. What we do have to do is:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This is a fix to #35455, i.e.:
In current code (daemon.createSpec()), tmpfs mount from --tmpfs is added
to list of mounts (
ms
), when the mount from IpcMounts() is added.While IpcMounts() is checking for existing mounts first, it does that
by using container.HasMountFor() function which only checks container.Mounts
but not container.Tmpfs.
Ultimately, the solution is to get rid of container.Tmpfs (moving its
data to container.Mounts). Current workaround is to add checking
of container.Tmpfs into container.HasMountFor().
A unit test case is included.
Unfortunately we can't call daemon.createSpec() from a unit test,
as the code relies a lot on various daemon structures to be initialized
properly, and it is hard to achieve. Therefore, we minimally mimick
the code flow of daemon.createSpec() -- barely enough to reproduce
the issue.