pkg/cri/server: optimizations in unmountRecursive()

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).

e8fb2c392f (r535450446)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2020-12-07 11:37:29 +01:00
parent 7572919201
commit 2374178c9b
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C

View File

@ -166,34 +166,23 @@ func openLogFile(path string) (*os.File, error) {
// unmountRecursive unmounts the target and all mounts underneath, starting with // unmountRecursive unmounts the target and all mounts underneath, starting with
// the deepest mount first. // the deepest mount first.
func unmountRecursive(ctx context.Context, target string) error { func unmountRecursive(ctx context.Context, target string) error {
mounts, err := mountinfo.GetMounts(nil) toUnmount, err := mountinfo.GetMounts(mountinfo.PrefixFilter(target))
if err != nil { if err != nil {
return err return err
} }
var toUnmount []string
for _, m := range mounts {
p, err := filepath.Rel(target, m.Mountpoint)
if err != nil {
return err
}
if !strings.HasPrefix(p, "..") {
toUnmount = append(toUnmount, m.Mountpoint)
}
}
// Make the deepest mount be first // Make the deepest mount be first
sort.Slice(toUnmount, func(i, j int) bool { sort.Slice(toUnmount, func(i, j int) bool {
return len(toUnmount[i]) > len(toUnmount[j]) return len(toUnmount[i].Mountpoint) > len(toUnmount[j].Mountpoint)
}) })
for i, mountPath := range toUnmount { for i, m := range toUnmount {
if err := mount.UnmountAll(mountPath, unix.MNT_DETACH); err != nil { if err := mount.UnmountAll(m.Mountpoint, unix.MNT_DETACH); err != nil {
if i == len(toUnmount)-1 { // last mount if i == len(toUnmount)-1 { // last mount
return err return err
} }
// This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem // This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem
log.G(ctx).WithError(err).Debugf("failed to unmount submount %s", mountPath) log.G(ctx).WithError(err).Debugf("failed to unmount submount %s", m.Mountpoint)
} }
} }
return nil return nil