blob: df2e99b6c180780915dafaf96a689976b1c160e9 [file] [log] [blame]
package snapshot
import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/mount"
"github.com/pkg/errors"
)
func (lm *localMounter) Mount() (string, error) {
lm.mu.Lock()
defer lm.mu.Unlock()
if lm.mounts == nil {
mounts, release, err := lm.mountable.Mount()
if err != nil {
return "", err
}
lm.mounts = mounts
lm.release = release
}
// Windows can only mount a single mount at a given location.
// Parent layers are carried in Options, opaquely to localMounter.
if len(lm.mounts) != 1 {
return "", errors.Wrapf(errdefs.ErrNotImplemented, "request to mount %d layers, only 1 is supported", len(lm.mounts))
}
m := lm.mounts[0]
if m.Type == "bind" || m.Type == "rbind" {
ro := false
for _, opt := range m.Options {
if opt == "ro" {
ro = true
break
}
}
if !ro {
return m.Source, nil
}
}
// Windows mounts always activate in-place, so the target of the mount must be the source directory.
// See https://github.com/containerd/containerd/pull/2366
dir := m.Source
if err := m.Mount(dir); err != nil {
return "", errors.Wrapf(err, "failed to mount in-place: %v", m)
}
lm.target = dir
return lm.target, nil
}
func (lm *localMounter) Unmount() error {
lm.mu.Lock()
defer lm.mu.Unlock()
if lm.target != "" {
if err := mount.Unmount(lm.target, 0); err != nil {
return err
}
lm.target = ""
}
if lm.release != nil {
return lm.release()
}
return nil
}