mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[vfs] Create recursive dir creation util.
Refactored the recursive dir creation util in runsc/boot/vfs.go to be more flexible. PiperOrigin-RevId: 327719100
This commit is contained in:
@@ -36,6 +36,7 @@ package vfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
@@ -782,6 +783,38 @@ func (vfs *VirtualFilesystem) SyncAllFilesystems(ctx context.Context) error {
|
||||
return retErr
|
||||
}
|
||||
|
||||
// MkdirAllAt recursively creates non-existent directories on the given path
|
||||
// (including the last component).
|
||||
func (vfs *VirtualFilesystem) MkdirAllAt(ctx context.Context, currentPath string, root VirtualDentry, creds *auth.Credentials, mkdirOpts *MkdirOptions) error {
|
||||
pop := &PathOperation{
|
||||
Root: root,
|
||||
Start: root,
|
||||
Path: fspath.Parse(currentPath),
|
||||
}
|
||||
stat, err := vfs.StatAt(ctx, creds, pop, &StatOptions{Mask: linux.STATX_TYPE})
|
||||
switch err {
|
||||
case nil:
|
||||
if stat.Mask&linux.STATX_TYPE == 0 || stat.Mode&linux.FileTypeMask != linux.ModeDirectory {
|
||||
return syserror.ENOTDIR
|
||||
}
|
||||
// Directory already exists.
|
||||
return nil
|
||||
case syserror.ENOENT:
|
||||
// Expected, we will create the dir.
|
||||
default:
|
||||
return fmt.Errorf("stat failed for %q during directory creation: %w", currentPath, err)
|
||||
}
|
||||
|
||||
// Recurse to ensure parent is created and then create the final directory.
|
||||
if err := vfs.MkdirAllAt(ctx, path.Dir(currentPath), root, creds, mkdirOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := vfs.MkdirAt(ctx, creds, pop, mkdirOpts); err != nil {
|
||||
return fmt.Errorf("failed to create directory %q: %w", currentPath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A VirtualDentry represents a node in a VFS tree, by combining a Dentry
|
||||
// (which represents a node in a Filesystem's tree) and a Mount (which
|
||||
// represents the Filesystem's position in a VFS mount tree).
|
||||
|
||||
+2
-30
@@ -16,7 +16,6 @@ package boot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -274,7 +273,7 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *config.C
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := c.makeSyntheticMount(ctx, submount.Destination, root, creds); err != nil {
|
||||
if err := c.k.VFS().MkdirAllAt(ctx, submount.Destination, root, creds, &vfs.MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.k.VFS().MountAt(ctx, creds, "", target, fsName, opts); err != nil {
|
||||
@@ -348,33 +347,6 @@ func (c *containerMounter) getMountNameAndOptionsVFS2(conf *config.Config, m *mo
|
||||
return fsName, opts, nil
|
||||
}
|
||||
|
||||
func (c *containerMounter) makeSyntheticMount(ctx context.Context, currentPath string, root vfs.VirtualDentry, creds *auth.Credentials) error {
|
||||
target := &vfs.PathOperation{
|
||||
Root: root,
|
||||
Start: root,
|
||||
Path: fspath.Parse(currentPath),
|
||||
}
|
||||
_, err := c.k.VFS().StatAt(ctx, creds, target, &vfs.StatOptions{})
|
||||
if err == nil {
|
||||
log.Debugf("Mount point %q already exists", currentPath)
|
||||
return nil
|
||||
}
|
||||
if err != syserror.ENOENT {
|
||||
return fmt.Errorf("stat failed for %q during mount point creation: %w", currentPath, err)
|
||||
}
|
||||
|
||||
// Recurse to ensure parent is created and then create the mount point.
|
||||
if err := c.makeSyntheticMount(ctx, path.Dir(currentPath), root, creds); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("Creating dir %q for mount point", currentPath)
|
||||
mkdirOpts := &vfs.MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true}
|
||||
if err := c.k.VFS().MkdirAt(ctx, creds, target, mkdirOpts); err != nil {
|
||||
return fmt.Errorf("failed to create directory %q for mount: %w", currentPath, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mountTmpVFS2 mounts an internal tmpfs at '/tmp' if it's safe to do so.
|
||||
// Technically we don't have to mount tmpfs at /tmp, as we could just rely on
|
||||
// the host /tmp, but this is a nice optimization, and fixes some apps that call
|
||||
@@ -503,7 +475,7 @@ func (c *containerMounter) mountSharedSubmountVFS2(ctx context.Context, conf *co
|
||||
|
||||
root := mns.Root()
|
||||
defer root.DecRef(ctx)
|
||||
if err := c.makeSyntheticMount(ctx, mount.Destination, root, creds); err != nil {
|
||||
if err := c.k.VFS().MkdirAllAt(ctx, mount.Destination, root, creds, &vfs.MkdirOptions{Mode: 0777, ForSyntheticMountpoint: true}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user