Loop umount'ing rootfs until there are no more mounts
This is simpler than trying to count how many successful mounts we made. Signed-off-by: Ian Campbell <ian.campbell@docker.com>
This commit is contained in:
parent
d63d2ecf6c
commit
d42cb88ba2
@ -39,19 +39,18 @@ type initProcess struct {
|
|||||||
// the reaper interface.
|
// the reaper interface.
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
id string
|
id string
|
||||||
bundle string
|
bundle string
|
||||||
console console.Console
|
console console.Console
|
||||||
io runc.IO
|
io runc.IO
|
||||||
runtime *runc.Runc
|
runtime *runc.Runc
|
||||||
status int
|
status int
|
||||||
exited time.Time
|
exited time.Time
|
||||||
pid int
|
pid int
|
||||||
closers []io.Closer
|
closers []io.Closer
|
||||||
stdin io.Closer
|
stdin io.Closer
|
||||||
stdio stdio
|
stdio stdio
|
||||||
rootfs string
|
rootfs string
|
||||||
nrRootMounts int // Number of rootfs overmounts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInitProcess(context context.Context, path, namespace string, r *shimapi.CreateTaskRequest) (*initProcess, error) {
|
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
|
// count the number of successful mounts so we can undo
|
||||||
// what was actually done rather than what should have been
|
// what was actually done rather than what should have been
|
||||||
// done.
|
// done.
|
||||||
nrRootMounts := 0
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if success {
|
if success {
|
||||||
return
|
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")
|
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 {
|
if err := m.Mount(rootfs); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
|
return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m)
|
||||||
}
|
}
|
||||||
nrRootMounts++
|
|
||||||
}
|
}
|
||||||
runtime := &runc.Runc{
|
runtime := &runc.Runc{
|
||||||
Command: r.Runtime,
|
Command: r.Runtime,
|
||||||
@ -110,8 +107,7 @@ func newInitProcess(context context.Context, path, namespace string, r *shimapi.
|
|||||||
stderr: r.Stderr,
|
stderr: r.Stderr,
|
||||||
terminal: r.Terminal,
|
terminal: r.Terminal,
|
||||||
},
|
},
|
||||||
rootfs: rootfs,
|
rootfs: rootfs,
|
||||||
nrRootMounts: nrRootMounts,
|
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
@ -253,7 +249,7 @@ func (p *initProcess) Delete(context context.Context) error {
|
|||||||
}
|
}
|
||||||
err = p.runtimeError(err, "OCI runtime delete failed")
|
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")
|
log.G(context).WithError(err2).Warn("Failed to cleanup rootfs mount")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = errors.Wrap(err2, "Failed rootfs umount")
|
err = errors.Wrap(err2, "Failed rootfs umount")
|
||||||
|
@ -22,19 +22,3 @@ func MountAll(mounts []Mount, target string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
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
|
|
||||||
}
|
|
||||||
|
@ -15,6 +15,25 @@ func Unmount(mount string, flags int) error {
|
|||||||
return unix.Unmount(mount, flags)
|
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
|
// parseMountOptions takes fstab style mount options and parses them for
|
||||||
// use with a standard mount() syscall
|
// use with a standard mount() syscall
|
||||||
func parseMountOptions(options []string) (int, string) {
|
func parseMountOptions(options []string) (int, string) {
|
||||||
|
@ -15,3 +15,7 @@ func (m *Mount) Mount(target string) error {
|
|||||||
func Unmount(mount string, flags int) error {
|
func Unmount(mount string, flags int) error {
|
||||||
return ErrNotImplementOnUnix
|
return ErrNotImplementOnUnix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnmountAll(mount string, flags int) error {
|
||||||
|
return ErrNotImplementOnUnix
|
||||||
|
}
|
||||||
|
@ -13,3 +13,7 @@ func (m *Mount) Mount(target string) error {
|
|||||||
func Unmount(mount string, flags int) error {
|
func Unmount(mount string, flags int) error {
|
||||||
return ErrNotImplementOnWindows
|
return ErrNotImplementOnWindows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UnmountAll(mount string, flags int) error {
|
||||||
|
return ErrNotImplementOnWindows
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user