Skip to content

is RecursiveUnmount needed? #21

@kolyshkin

Description

@kolyshkin

Today I was looking into RecursiveUnmount code and thought we can optimize it by adding the fast path, like this:

 // RecursiveUnmount unmounts the target and all mounts underneath, starting with
 // the deepsest mount first.
 func RecursiveUnmount(target string) error {
+       // Fast path: if we can unmount target, there are no submounts!
+       if err := unmount(target, 0); err == nil {
+               return nil
+       }
+
        mounts, err := mountinfo.GetMounts(mountinfo.PrefixFilter(target))
        if err != nil {
                return err

The idea is, if there are other mounts under target, we'll go the usual slow way, but if not, all it takes a single syscall.

When I read the umount(2) man page for the umphteen time, to confirm my gut feeling I should NOT use MNT_DETACH in the fast path, and found this gem:

immediately disconnect the filesystem and all filesystems
mounted below it from each other and from the mount table

This means that MNT_DETACH performs a recursive unmount. Since we do use MNT_DETACH from RecursiveUnmount anyway, it seems all of it, in its entirety, can be replaced by a single umount(2) with MNT_DETACH.

@cpuguy83 can you please shed some light on how you came with RecursiveUnmount in the first place? I tracked its inception down to PR moby/moby#31012 (moby/moby@54dcbab#diff-ce9e7d50400d88435b2be4f4cd9b7b23R61) but it's not very clear why it was added. I am surely very interested in your other input on this topic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions