Use mount.Target to specify subdirectory of rootfs mount

- Add Target to mount.Mount.
- Add UnmountMounts to unmount a list of mounts in reverse order.
- Add UnmountRecursive to unmount deepest mount first for a given target, using
moby/sys/mountinfo.

Signed-off-by: Edgar Lee <edgarhinshunlee@gmail.com>
This commit is contained in:
Edgar Lee
2023-01-23 13:36:28 -05:00
parent 753bfd6575
commit 34d5878185
26 changed files with 282 additions and 65 deletions

View File

@@ -16,6 +16,12 @@
package mount
import (
"fmt"
"github.com/containerd/continuity/fs"
)
// Mount is the lingua franca of containerd. A mount represents a
// serialized mount syscall. Components either emit or consume mounts.
type Mount struct {
@@ -24,12 +30,16 @@ type Mount struct {
// Source specifies where to mount from. Depending on the host system, this
// can be a source path or device.
Source string
// Target specifies an optional subdirectory as a mountpoint. It assumes that
// the subdirectory exists in a parent mount.
Target string
// Options contains zero or more fstab-style mount options. Typically,
// these are platform specific.
Options []string
}
// All mounts all the provided mounts to the provided target
// All mounts all the provided mounts to the provided target. If submounts are
// present, it assumes that parent mounts come before child mounts.
func All(mounts []Mount, target string) error {
for _, m := range mounts {
if err := m.Mount(target); err != nil {
@@ -38,3 +48,30 @@ func All(mounts []Mount, target string) error {
}
return nil
}
// UnmountMounts unmounts all the mounts under a target in the reverse order of
// the mounts array provided.
func UnmountMounts(mounts []Mount, target string, flags int) error {
for i := len(mounts) - 1; i >= 0; i-- {
mountpoint, err := fs.RootPath(target, mounts[i].Target)
if err != nil {
return err
}
if err := UnmountAll(mountpoint, flags); err != nil {
if i == len(mounts)-1 { // last mount
return err
}
}
}
return nil
}
// Mount to the provided target path.
func (m *Mount) Mount(target string) error {
target, err := fs.RootPath(target, m.Target)
if err != nil {
return fmt.Errorf("failed to join path %q with root %q: %w", m.Target, target, err)
}
return m.mount(target)
}