summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/gofer/file.go
diff options
context:
space:
mode:
authorNicolas Lacasse <nlacasse@google.com>2018-08-07 11:42:29 -0700
committerShentubot <shentubot@google.com>2018-08-07 11:43:41 -0700
commita38f41b4643520a3b2a078e73ec012ffd3f71f54 (patch)
treec2dc156a16f2a2643b418295a9a6c21bdc0b0c38 /pkg/sentry/fs/gofer/file.go
parentc348d0786388ded1a4bad3c98000b4653724c764 (diff)
fs: Add new cache policy "remote_revalidate".
This CL adds a new cache-policy for gofer filesystems that uses the host page cache, but causes dirents to be reloaded on each Walk, and does not cache readdir results. This policy is useful when the remote filesystem may change out from underneath us, as any remote changes will be reflected on the next Walk. Importantly, this cache policy is only consistent if we do not use gVisor's internal page cache, since that page cache is tied to the Inode and may be thrown away upon Revalidation. This cache policy should only be used when the gofer supports donating host FDs, since then gVisor will make use of the host kernel page cache, which will be consistent for all open files in the gofer. In fact, a panic will be raised if a file is opened without a donated FD. PiperOrigin-RevId: 207752937 Change-Id: I233cb78b4695bbe00a4605ae64080a47629329b8
Diffstat (limited to 'pkg/sentry/fs/gofer/file.go')
-rw-r--r--pkg/sentry/fs/gofer/file.go13
1 files changed, 12 insertions, 1 deletions
diff --git a/pkg/sentry/fs/gofer/file.go b/pkg/sentry/fs/gofer/file.go
index 46a6bbd5d..c4a210656 100644
--- a/pkg/sentry/fs/gofer/file.go
+++ b/pkg/sentry/fs/gofer/file.go
@@ -15,6 +15,7 @@
package gofer
import (
+ "fmt"
"syscall"
"gvisor.googlesource.com/gvisor/pkg/log"
@@ -72,6 +73,17 @@ func NewFile(ctx context.Context, dirent *fs.Dirent, name string, flags fs.FileF
flags.Pread = true
flags.Pwrite = true
+ if fs.IsFile(dirent.Inode.StableAttr) {
+ // If cache policy is "remote revalidating", then we must
+ // ensure that we have a host FD. Otherwise, the
+ // sentry-internal page cache will be used, and we can end up
+ // in an inconsistent state if the remote file changes.
+ cp := dirent.Inode.InodeOperations.(*inodeOperations).session().cachePolicy
+ if cp == cacheRemoteRevalidating && handles.Host == nil {
+ panic(fmt.Sprintf("remote-revalidating cache policy requires gofer to donate host FD, but file %q did not have host FD", name))
+ }
+ }
+
f := &fileOperations{
inodeOperations: i,
handles: handles,
@@ -202,7 +214,6 @@ func (f *fileOperations) Write(ctx context.Context, file *fs.File, src usermem.I
err = f.inodeOperations.cachingInodeOps.WriteOut(ctx, file.Dirent.Inode)
}
return n, err
-
}
return src.CopyInTo(ctx, f.handles.readWriterAt(ctx, offset))
}