diff options
author | Brielle Broder <bbroder@google.com> | 2018-08-10 14:31:56 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-08-10 14:33:20 -0700 |
commit | 4ececd8e8d1124cdd0884480bda5fabd2b48aa8d (patch) | |
tree | 5a4d6673db4dad19df91a7901d4e6387e09d83ab /pkg/sentry/fs/dirent.go | |
parent | d5b702b64f05a200ed94f0cd977d3f84dae01162 (diff) |
Enable checkpoint/restore in cases of UDS use.
Previously, processes which used file-system Unix Domain Sockets could not be
checkpoint-ed in runsc because the sockets were saved with their inode
numbers which do not necessarily remain the same upon restore. Now,
the sockets are also saved with their paths so that the new inodes
can be determined for the sockets based on these paths after restoring.
Tests for cases with UDS use are included. Test cleanup to come.
PiperOrigin-RevId: 208268781
Change-Id: Ieaa5d5d9a64914ca105cae199fd8492710b1d7ec
Diffstat (limited to 'pkg/sentry/fs/dirent.go')
-rw-r--r-- | pkg/sentry/fs/dirent.go | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/pkg/sentry/fs/dirent.go b/pkg/sentry/fs/dirent.go index 4658d044f..821cc5789 100644 --- a/pkg/sentry/fs/dirent.go +++ b/pkg/sentry/fs/dirent.go @@ -385,6 +385,19 @@ func (d *Dirent) fullName(root *Dirent) (string, bool) { return s, reachable } +// MountRoot finds and returns the mount-root for a given dirent. +func (d *Dirent) MountRoot() *Dirent { + renameMu.RLock() + defer renameMu.RUnlock() + + mountRoot := d + for !mountRoot.mounted && mountRoot.parent != nil { + mountRoot = mountRoot.parent + } + mountRoot.IncRef() + return mountRoot +} + func (d *Dirent) freeze() { if d.frozen { // Already frozen. @@ -665,6 +678,16 @@ func (d *Dirent) Create(ctx context.Context, root *Dirent, name string, flags Fi } child := file.Dirent + d.finishCreate(child, name) + + // Return the reference and the new file. When the last reference to + // the file is dropped, file.Dirent may no longer be cached. + return file, nil +} + +// finishCreate validates the created file, adds it as a child of this dirent, +// and notifies any watchers. +func (d *Dirent) finishCreate(child *Dirent, name string) { // Sanity check c, its name must be consistent. if child.name != name { panic(fmt.Sprintf("create from %q to %q returned unexpected name %q", d.name, name, child.name)) @@ -697,10 +720,6 @@ func (d *Dirent) Create(ctx context.Context, root *Dirent, name string, flags Fi // Allow the file system to take extra references on c. child.maybeExtendReference() - - // Return the reference and the new file. When the last reference to - // the file is dropped, file.Dirent may no longer be cached. - return file, nil } // genericCreate executes create if name does not exist. Removes a negative Dirent at name if @@ -718,11 +737,6 @@ func (d *Dirent) genericCreate(ctx context.Context, root *Dirent, name string, c return syscall.ENOENT } - // Execute the create operation. - if err := create(); err != nil { - return err - } - // Remove any negative Dirent. We've already asserted above with d.exists // that the only thing remaining here can be a negative Dirent. if w, ok := d.children[name]; ok { @@ -745,7 +759,8 @@ func (d *Dirent) genericCreate(ctx context.Context, root *Dirent, name string, c w.Drop() } - return nil + // Execute the create operation. + return create() } // CreateLink creates a new link in this directory. @@ -797,23 +812,29 @@ func (d *Dirent) CreateDirectory(ctx context.Context, root *Dirent, name string, } // Bind satisfies the InodeOperations interface; otherwise same as GetFile. -func (d *Dirent) Bind(ctx context.Context, root *Dirent, name string, socket unix.BoundEndpoint, perms FilePermissions) error { +func (d *Dirent) Bind(ctx context.Context, root *Dirent, name string, data unix.BoundEndpoint, perms FilePermissions) (*Dirent, error) { d.dirMu.Lock() defer d.dirMu.Unlock() d.mu.Lock() defer d.mu.Unlock() + var childDir *Dirent err := d.genericCreate(ctx, root, name, func() error { - if err := d.Inode.Bind(ctx, name, socket, perms); err != nil { - return err + var e error + childDir, e = d.Inode.Bind(ctx, name, data, perms) + if e != nil { + return e } - d.Inode.Watches.Notify(name, linux.IN_CREATE, 0) + d.finishCreate(childDir, name) return nil }) if err == syscall.EEXIST { - return syscall.EADDRINUSE + return nil, syscall.EADDRINUSE + } + if err != nil { + return nil, err } - return err + return childDir, err } // CreateFifo creates a new named pipe under this dirent. |