[vfs] Allow mountpoint to be an existing non-directory.
Unlike linux mount(2), OCI spec allows mounting on top of an existing non-directory file. PiperOrigin-RevId: 327914342
This commit is contained in:
parent
9607515aed
commit
17bc5c1b00
|
@ -18,12 +18,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"path"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||||
"gvisor.dev/gvisor/pkg/context"
|
"gvisor.dev/gvisor/pkg/context"
|
||||||
|
"gvisor.dev/gvisor/pkg/fspath"
|
||||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||||
"gvisor.dev/gvisor/pkg/syserror"
|
"gvisor.dev/gvisor/pkg/syserror"
|
||||||
)
|
)
|
||||||
|
@ -888,6 +890,30 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeSyntheticMountpoint creates parent directories of target if they do not
|
||||||
|
// exist and attempts to create a directory for the mountpoint. If a
|
||||||
|
// non-directory file already exists there then we allow it.
|
||||||
|
func (vfs *VirtualFilesystem) MakeSyntheticMountpoint(ctx context.Context, target string, root VirtualDentry, creds *auth.Credentials) error {
|
||||||
|
mkdirOpts := &MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true}
|
||||||
|
|
||||||
|
// Make sure the parent directory of target exists.
|
||||||
|
if err := vfs.MkdirAllAt(ctx, path.Dir(target), root, creds, mkdirOpts); err != nil {
|
||||||
|
return fmt.Errorf("failed to create parent directory of mountpoint %q: %w", target, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to mkdir the final component. If a file (of any type) exists
|
||||||
|
// then we let allow mounting on top of that because we do not require the
|
||||||
|
// target to be an existing directory, unlike Linux mount(2).
|
||||||
|
if err := vfs.MkdirAt(ctx, creds, &PathOperation{
|
||||||
|
Root: root,
|
||||||
|
Start: root,
|
||||||
|
Path: fspath.Parse(target),
|
||||||
|
}, mkdirOpts); err != nil && err != syserror.EEXIST {
|
||||||
|
return fmt.Errorf("failed to create mountpoint %q: %w", target, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// manglePath replaces ' ', '\t', '\n', and '\\' with their octal equivalents.
|
// manglePath replaces ' ', '\t', '\n', and '\\' with their octal equivalents.
|
||||||
// See Linux fs/seq_file.c:mangle_path.
|
// See Linux fs/seq_file.c:mangle_path.
|
||||||
func manglePath(p string) string {
|
func manglePath(p string) string {
|
||||||
|
|
|
@ -292,7 +292,7 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *config.C
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.k.VFS().MkdirAllAt(ctx, submount.Destination, root, creds, &vfs.MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true}); err != nil {
|
if err := c.k.VFS().MakeSyntheticMountpoint(ctx, submount.Destination, root, creds); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mnt, err := c.k.VFS().MountAt(ctx, creds, "", target, fsName, opts)
|
mnt, err := c.k.VFS().MountAt(ctx, creds, "", target, fsName, opts)
|
||||||
|
@ -496,7 +496,7 @@ func (c *containerMounter) mountSharedSubmountVFS2(ctx context.Context, conf *co
|
||||||
|
|
||||||
root := mns.Root()
|
root := mns.Root()
|
||||||
defer root.DecRef(ctx)
|
defer root.DecRef(ctx)
|
||||||
if err := c.k.VFS().MkdirAllAt(ctx, mount.Destination, root, creds, &vfs.MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true}); err != nil {
|
if err := c.k.VFS().MakeSyntheticMountpoint(ctx, mount.Destination, root, creds); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue