Skip to content
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

mount: replace mountinfo handling with moby/sys/mountinfo #4578

Merged
merged 6 commits into from Jan 12, 2021

Conversation

thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Sep 22, 2020

Trying to reduce duplicated effort in maintaining a mountinfo parser, this patch replaces the local implementation with the implementation in github.com/moby/sys, which is actively maintained and contains various optimizations.

Using a temporary vendor, pending moby/sys#32 and moby/sys#34 merged

With this change, the only consumer of mount.Self() is containerd/cri. mount.PID() looks to be unused altogether, so both could potentially be removed if containerd/cri is updated. removed

@k8s-ci-robot
Copy link

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@theopenlab-ci
Copy link

theopenlab-ci bot commented Sep 22, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Sep 22, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Sep 22, 2020

Build succeeded.

@fuweid
Copy link
Member

fuweid commented Sep 22, 2020

But it brings new dependencies into containerd 😂

@estesp
Copy link
Member

estesp commented Sep 22, 2020

New dependencies, but fewer total lines of code? "+5,059 −8,426" ❓ 😂

@thaJeztah
Copy link
Member Author

New dependencies, but fewer total lines of code? "+5,059 −8,426" ❓ 😂

Yeah, most of that is currently because of golang.org/x/sys and containerd/console. If we tag a new release of containerd/console, I can vendor it separately (nudge nudge 😉)

@theopenlab-ci
Copy link

theopenlab-ci bot commented Sep 28, 2020

Build succeeded.

@thaJeztah thaJeztah force-pushed the use_moby_sys branch 2 times, most recently from 9ad3dfd to 6363e49 Compare September 28, 2020 09:38
@theopenlab-ci
Copy link

theopenlab-ci bot commented Sep 28, 2020

Build succeeded.

"github.com/pkg/errors"
)

// Lookup returns the mount info corresponds to the path.
func Lookup(dir string) (Info, error) {
dir = filepath.Clean(dir)

mounts, err := Self()
m, err := mountinfo.GetMounts(mountinfo.SingleEntryFilter(dir))
Copy link
Contributor

Choose a reason for hiding this comment

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

Alas, this is wrong. Previously this function was capable of returning info for e.g. mount point /mnt given the argument of /mnt/some/thing. Currently it looks for /mnt/some/thing.

You need mountinfo.ParentsFilter(dir), sort, and take the longest one -- same as in getSourceMount in moby/moby.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also think we can implement this in mountinfo itself, as it's been used from a few places.

Copy link
Member Author

Choose a reason for hiding this comment

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

updated; PTAL

@theopenlab-ci
Copy link

theopenlab-ci bot commented Oct 1, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Oct 6, 2020

Build succeeded.

@thaJeztah thaJeztah force-pushed the use_moby_sys branch 2 times, most recently from b7b0ed3 to d92d3a3 Compare October 29, 2020 22:28
@thaJeztah thaJeztah changed the title [draft] mount: replace mountinfo handling with moby/sys/mountinfo mount: replace mountinfo handling with moby/sys/mountinfo Oct 29, 2020
@theopenlab-ci
Copy link

theopenlab-ci bot commented Oct 29, 2020

Build succeeded.

@thaJeztah thaJeztah marked this pull request as ready for review October 29, 2020 22:47
@thaJeztah
Copy link
Member Author

Moving this out of draft; removed the remaining uses in the CRI code now that it was integrated

@estesp @kolyshkin @cpuguy83 PTAL

@theopenlab-ci
Copy link

theopenlab-ci bot commented Nov 10, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Nov 13, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Dec 3, 2020

Build succeeded.

mount/mountinfo.go Outdated Show resolved Hide resolved
@@ -161,7 +162,7 @@ func openLogFile(path string) (*os.File, error) {
// unmountRecursive unmounts the target and all mounts underneath, starting with
// the deepest mount first.
func unmountRecursive(ctx context.Context, target string) error {
mounts, err := mount.Self()
mounts, err := mountinfo.GetMounts(nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

Two things.

  1. This might benefit from using PrefixFilter (and when the logic will be simplified -- there's no need to do filepath.Rel and strings.HasPrefix below).

  2. Not really related to this, but there's a little known fact that umount(MNT_DETACH) is actually recursive in Linux, IOW this function can be replaced with unix.Umount(target, unix.MNT_DETACH) (or mount.UnmountAll(target, unix.MNT_DETACH)) -- provided that target itself is a mount point. Related: mount.RecursiveUnmount: add a fast path moby/sys#26

  3. Definitely not related to this, but I took a look at pkg/mount.UnmountAll and 😮 it retries umount without a delay on any error rather than EINVAL forever. This means, for example, if someone denies umount syscall using seccomp, we'll end up calling umount in a busy loop indefinitely.

Copy link
Member Author

Choose a reason for hiding this comment

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

@kolyshkin would that mean we can replace this whole function with moby/mount.RecursiveUnmount(), or would we still need some of the logic below?

Copy link
Member Author

Choose a reason for hiding this comment

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

it retries umount without a delay on any error rather than EINVAL

I see it returns on errors (only returns nil if it was an EINVAL), or is that not the part you were looking at?

if err == unix.EINVAL {
return nil
}
return err

Copy link
Contributor

Choose a reason for hiding this comment

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

I see it returns on errors (only returns nil if it was an EINVAL), or is that not the part you were looking at?

You're right, I misread the code in there :) so item 3 above can be crossed out.

Re. item 2, I finally understood the logic of containerd's UnmountAll() (it works around overmounts, i.e. when the same mountpoint being mounted to multiple times) and I think we should do something like this in moby/sys/mount, too. In the meantime, let's leave this as is, IOW ACK.

@kolyshkin
Copy link
Contributor

@thaJeztah thanks for working on this! LGTM overall, maybe makes sense to squash the first two (or three?) commits.

@thaJeztah
Copy link
Member Author

@kolyshkin I added the prefix-filter, and removed the local prefix checks; kept it as a separate commit for easier reviewing, but I can squash.

IOW this function can be replaced with unix.Umount(target, unix.MNT_DETACH) (or mount.UnmountAll(target, unix.MNT_DETACH))

Do you think we should replace it here? (mostly wondering if the current logic was addressing specific (corner) cases)

@theopenlab-ci
Copy link

theopenlab-ci bot commented Dec 7, 2020

Build succeeded.

@theopenlab-ci
Copy link

theopenlab-ci bot commented Dec 7, 2020

Build succeeded.

Trying to reduce duplicated effort in maintaining a mountinfo
parser, this patch replaces the local implementation with the
implementation in github.com/moby/sys, which is actively maintained
and contains various optimizations.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Use a PrefixFilter() to get only the mounts we're interested in,
which removes the need to manually filter mounts from the mountinfo
results.

Additional optimizations can be made, as:

> ... there's a little known fact that `umount(MNT_DETACH)` is actually
> recursive in Linux, IOW this function can be replaced with
> `unix.Umount(target, unix.MNT_DETACH)` (or `mount.UnmountAll(target, unix.MNT_DETACH)`
>  (provided that target itself is a mount point).

containerd@e8fb2c3#r535450446

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah
Copy link
Member Author

Rebased to get a fresh run of CI

@AkihiroSuda @estesp @kolyshkin @cpuguy83 PTAL

@theopenlab-ci
Copy link

theopenlab-ci bot commented Jan 8, 2021

Build succeeded.

mount/mountinfo.go Outdated Show resolved Hide resolved
mount/mountinfo_bsd.go Outdated Show resolved Hide resolved
@@ -40,23 +41,20 @@ func SetTempMountLocation(root string) error {

// CleanupTempMounts all temp mounts and remove the directories
func CleanupTempMounts(flags int) (warnings []error, err error) {
mounts, err := Self()
mounts, err := mountinfo.GetMounts(mountinfo.PrefixFilter(tempMountLocation))
Copy link
Contributor

Choose a reason for hiding this comment

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

Alas we can't have a "fast path" I talked about earlier in here, since tempMountLocation is not a mount point per se.

In case containerd itself is doing all those mounts, those can be saved in a list, and we should go over that list in here (instead of reading mountinfo) -- that would be a worthwhile optimization.

In case a user does those mounts, this is unfortunate and there's nothing we can do but read mountinfo.

In any case, this can be addressed later.

Copy link
Contributor

@kolyshkin kolyshkin left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@dmcgowan dmcgowan left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member

@estesp estesp left a comment

Choose a reason for hiding this comment

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

LGTM

@estesp estesp merged commit e62d03b into containerd:master Jan 12, 2021
@thaJeztah thaJeztah deleted the use_moby_sys branch January 12, 2021 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants