summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyush Ranjan <ayushranjan@google.com>2020-08-20 16:25:57 -0700
committerAndrei Vagin <avagin@gmail.com>2020-09-09 17:53:10 -0700
commitfc68f90fc066473951521b6bdd3adfd6c7dfc61f (patch)
tree19b92be933e18d23865623b60da32af400cc07ac
parent4c758df8075628e10a58c0117a17dc5c41d57be9 (diff)
[vfs] Create recursive dir creation util.
Refactored the recursive dir creation util in runsc/boot/vfs.go to be more flexible. PiperOrigin-RevId: 327719100
-rw-r--r--pkg/sentry/vfs/vfs.go33
-rw-r--r--runsc/boot/vfs.go32
2 files changed, 35 insertions, 30 deletions
diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go
index 8a79e1325..ec27562d6 100644
--- a/pkg/sentry/vfs/vfs.go
+++ b/pkg/sentry/vfs/vfs.go
@@ -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).
diff --git a/runsc/boot/vfs.go b/runsc/boot/vfs.go
index 3da7a64f0..f27a6ff6b 100644
--- a/runsc/boot/vfs.go
+++ b/runsc/boot/vfs.go
@@ -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
}