diff --git a/linux/shim/init.go b/linux/shim/init.go index f54daaaf7..f34defe70 100644 --- a/linux/shim/init.go +++ b/linux/shim/init.go @@ -39,19 +39,18 @@ type initProcess struct { // the reaper interface. mu sync.Mutex - id string - bundle string - console console.Console - io runc.IO - runtime *runc.Runc - status int - exited time.Time - pid int - closers []io.Closer - stdin io.Closer - stdio stdio - rootfs string - nrRootMounts int // Number of rootfs overmounts + id string + bundle string + console console.Console + io runc.IO + runtime *runc.Runc + status int + exited time.Time + pid int + closers []io.Closer + stdin io.Closer + stdio stdio + rootfs string } func newInitProcess(context context.Context, path, namespace string, r *shimapi.CreateTaskRequest) (*initProcess, error) { @@ -73,12 +72,11 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi. // count the number of successful mounts so we can undo // what was actually done rather than what should have been // done. - nrRootMounts := 0 defer func() { if success { return } - if err2 := mount.UnmountN(rootfs, 0, nrRootMounts); err2 != nil { + if err2 := mount.UnmountAll(rootfs, 0); err2 != nil { log.G(context).WithError(err2).Warn("Failed to cleanup rootfs mount") } }() @@ -91,7 +89,6 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi. if err := m.Mount(rootfs); err != nil { return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m) } - nrRootMounts++ } runtime := &runc.Runc{ Command: r.Runtime, @@ -110,8 +107,7 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi. stderr: r.Stderr, terminal: r.Terminal, }, - rootfs: rootfs, - nrRootMounts: nrRootMounts, + rootfs: rootfs, } var ( err error @@ -253,7 +249,7 @@ func (p *initProcess) Delete(context context.Context) error { } err = p.runtimeError(err, "OCI runtime delete failed") - if err2 := mount.UnmountN(p.rootfs, 0, p.nrRootMounts); err2 != nil { + if err2 := mount.UnmountAll(p.rootfs, 0); err2 != nil { log.G(context).WithError(err2).Warn("Failed to cleanup rootfs mount") if err == nil { err = errors.Wrap(err2, "Failed rootfs umount") diff --git a/mount/mount.go b/mount/mount.go index 2ef4a0164..94086f178 100644 --- a/mount/mount.go +++ b/mount/mount.go @@ -22,19 +22,3 @@ func MountAll(mounts []Mount, target string) error { } return nil } - -// UnmountN tries to unmount the given mount point nr times, which is -// useful for undoing a stack of mounts on the same mount -// point. Returns the first error encountered, but always attempts the -// full nr umounts. -func UnmountN(mount string, flags, nr int) error { - var err error - for i := 0; i < nr; i++ { - if err2 := Unmount(mount, flags); err2 != nil { - if err == nil { - err = err2 - } - } - } - return err -} diff --git a/mount/mount_linux.go b/mount/mount_linux.go index 86df8bbc1..5995051b8 100644 --- a/mount/mount_linux.go +++ b/mount/mount_linux.go @@ -15,6 +15,25 @@ func Unmount(mount string, flags int) error { return unix.Unmount(mount, flags) } +// UnmountAll repeatedly unmounts the given mount point until there +// are no mounts remaining (EINVAL is returned by mount), which is +// useful for undoing a stack of mounts on the same mount point. +func UnmountAll(mount string, flags int) error { + for { + if err := Unmount(mount, flags); err != nil { + // EINVAL is returned if the target is not a + // mount point, indicating that we are + // done. It can also indicate a few other + // things (such as invalid flags) which we + // unfortunately end up squelching here too. + if err == unix.EINVAL { + return nil + } + return err + } + } +} + // parseMountOptions takes fstab style mount options and parses them for // use with a standard mount() syscall func parseMountOptions(options []string) (int, string) { diff --git a/mount/mount_unix.go b/mount/mount_unix.go index 32ea2691a..23467a8cc 100644 --- a/mount/mount_unix.go +++ b/mount/mount_unix.go @@ -15,3 +15,7 @@ func (m *Mount) Mount(target string) error { func Unmount(mount string, flags int) error { return ErrNotImplementOnUnix } + +func UnmountAll(mount string, flags int) error { + return ErrNotImplementOnUnix +} diff --git a/mount/mount_windows.go b/mount/mount_windows.go index 35dead411..8eeca6817 100644 --- a/mount/mount_windows.go +++ b/mount/mount_windows.go @@ -13,3 +13,7 @@ func (m *Mount) Mount(target string) error { func Unmount(mount string, flags int) error { return ErrNotImplementOnWindows } + +func UnmountAll(mount string, flags int) error { + return ErrNotImplementOnWindows +}