mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add limit_host_fd_translation Gofer mount option.
PiperOrigin-RevId: 266177409
This commit is contained in:
committed by
Nicolas Lacasse
parent
6e8fc27dc5
commit
36a8949b2a
@@ -66,10 +66,8 @@ type CachingInodeOperations struct {
|
||||
// mfp is used to allocate memory that caches backingFile's contents.
|
||||
mfp pgalloc.MemoryFileProvider
|
||||
|
||||
// forcePageCache indicates the sentry page cache should be used regardless
|
||||
// of whether the platform supports host mapped I/O or not. This must not be
|
||||
// modified after inode creation.
|
||||
forcePageCache bool
|
||||
// opts contains options. opts is immutable.
|
||||
opts CachingInodeOperationsOptions
|
||||
|
||||
attrMu sync.Mutex `state:"nosave"`
|
||||
|
||||
@@ -116,6 +114,20 @@ type CachingInodeOperations struct {
|
||||
refs frameRefSet
|
||||
}
|
||||
|
||||
// CachingInodeOperationsOptions configures a CachingInodeOperations.
|
||||
//
|
||||
// +stateify savable
|
||||
type CachingInodeOperationsOptions struct {
|
||||
// If ForcePageCache is true, use the sentry page cache even if a host file
|
||||
// descriptor is available.
|
||||
ForcePageCache bool
|
||||
|
||||
// If LimitHostFDTranslation is true, apply maxFillRange() constraints to
|
||||
// host file descriptor mappings returned by
|
||||
// CachingInodeOperations.Translate().
|
||||
LimitHostFDTranslation bool
|
||||
}
|
||||
|
||||
// CachedFileObject is a file that may require caching.
|
||||
type CachedFileObject interface {
|
||||
// ReadToBlocksAt reads up to dsts.NumBytes() bytes from the file to dsts,
|
||||
@@ -159,7 +171,7 @@ type CachedFileObject interface {
|
||||
|
||||
// NewCachingInodeOperations returns a new CachingInodeOperations backed by
|
||||
// a CachedFileObject and its initial unstable attributes.
|
||||
func NewCachingInodeOperations(ctx context.Context, backingFile CachedFileObject, uattr fs.UnstableAttr, forcePageCache bool) *CachingInodeOperations {
|
||||
func NewCachingInodeOperations(ctx context.Context, backingFile CachedFileObject, uattr fs.UnstableAttr, opts CachingInodeOperationsOptions) *CachingInodeOperations {
|
||||
mfp := pgalloc.MemoryFileProviderFromContext(ctx)
|
||||
if mfp == nil {
|
||||
panic(fmt.Sprintf("context.Context %T lacks non-nil value for key %T", ctx, pgalloc.CtxMemoryFileProvider))
|
||||
@@ -167,7 +179,7 @@ func NewCachingInodeOperations(ctx context.Context, backingFile CachedFileObject
|
||||
return &CachingInodeOperations{
|
||||
backingFile: backingFile,
|
||||
mfp: mfp,
|
||||
forcePageCache: forcePageCache,
|
||||
opts: opts,
|
||||
attr: uattr,
|
||||
hostFileMapper: NewHostFileMapper(),
|
||||
}
|
||||
@@ -763,7 +775,7 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
|
||||
// and memory mappings, and false if c.cache may contain data cached from
|
||||
// c.backingFile.
|
||||
func (c *CachingInodeOperations) useHostPageCache() bool {
|
||||
return !c.forcePageCache && c.backingFile.FD() >= 0
|
||||
return !c.opts.ForcePageCache && c.backingFile.FD() >= 0
|
||||
}
|
||||
|
||||
// AddMapping implements memmap.Mappable.AddMapping.
|
||||
@@ -835,11 +847,15 @@ func (c *CachingInodeOperations) CopyMapping(ctx context.Context, ms memmap.Mapp
|
||||
func (c *CachingInodeOperations) Translate(ctx context.Context, required, optional memmap.MappableRange, at usermem.AccessType) ([]memmap.Translation, error) {
|
||||
// Hot path. Avoid defer.
|
||||
if c.useHostPageCache() {
|
||||
mr := optional
|
||||
if c.opts.LimitHostFDTranslation {
|
||||
mr = maxFillRange(required, optional)
|
||||
}
|
||||
return []memmap.Translation{
|
||||
{
|
||||
Source: optional,
|
||||
Source: mr,
|
||||
File: c,
|
||||
Offset: optional.Start,
|
||||
Offset: mr.Start,
|
||||
Perms: usermem.AnyAccess,
|
||||
},
|
||||
}, nil
|
||||
|
||||
@@ -61,7 +61,7 @@ func TestSetPermissions(t *testing.T) {
|
||||
uattr := fs.WithCurrentTime(ctx, fs.UnstableAttr{
|
||||
Perms: fs.FilePermsFromMode(0444),
|
||||
})
|
||||
iops := NewCachingInodeOperations(ctx, noopBackingFile{}, uattr, false /*forcePageCache*/)
|
||||
iops := NewCachingInodeOperations(ctx, noopBackingFile{}, uattr, CachingInodeOperationsOptions{})
|
||||
defer iops.Release()
|
||||
|
||||
perms := fs.FilePermsFromMode(0777)
|
||||
@@ -150,7 +150,7 @@ func TestSetTimestamps(t *testing.T) {
|
||||
ModificationTime: epoch,
|
||||
StatusChangeTime: epoch,
|
||||
}
|
||||
iops := NewCachingInodeOperations(ctx, noopBackingFile{}, uattr, false /*forcePageCache*/)
|
||||
iops := NewCachingInodeOperations(ctx, noopBackingFile{}, uattr, CachingInodeOperationsOptions{})
|
||||
defer iops.Release()
|
||||
|
||||
if err := iops.SetTimestamps(ctx, nil, test.ts); err != nil {
|
||||
@@ -188,7 +188,7 @@ func TestTruncate(t *testing.T) {
|
||||
uattr := fs.UnstableAttr{
|
||||
Size: 0,
|
||||
}
|
||||
iops := NewCachingInodeOperations(ctx, noopBackingFile{}, uattr, false /*forcePageCache*/)
|
||||
iops := NewCachingInodeOperations(ctx, noopBackingFile{}, uattr, CachingInodeOperationsOptions{})
|
||||
defer iops.Release()
|
||||
|
||||
if err := iops.Truncate(ctx, nil, uattr.Size); err != nil {
|
||||
@@ -280,7 +280,7 @@ func TestRead(t *testing.T) {
|
||||
uattr := fs.UnstableAttr{
|
||||
Size: int64(len(buf)),
|
||||
}
|
||||
iops := NewCachingInodeOperations(ctx, newSliceBackingFile(buf), uattr, false /*forcePageCache*/)
|
||||
iops := NewCachingInodeOperations(ctx, newSliceBackingFile(buf), uattr, CachingInodeOperationsOptions{})
|
||||
defer iops.Release()
|
||||
|
||||
// Expect the cache to be initially empty.
|
||||
@@ -336,7 +336,7 @@ func TestWrite(t *testing.T) {
|
||||
uattr := fs.UnstableAttr{
|
||||
Size: int64(len(buf)),
|
||||
}
|
||||
iops := NewCachingInodeOperations(ctx, newSliceBackingFile(buf), uattr, false /*forcePageCache*/)
|
||||
iops := NewCachingInodeOperations(ctx, newSliceBackingFile(buf), uattr, CachingInodeOperationsOptions{})
|
||||
defer iops.Release()
|
||||
|
||||
// Expect the cache to be initially empty.
|
||||
|
||||
@@ -54,6 +54,10 @@ const (
|
||||
// sandbox using files backed by the gofer. If set to false, unix sockets
|
||||
// cannot be bound to gofer files without an overlay on top.
|
||||
privateUnixSocketKey = "privateunixsocket"
|
||||
|
||||
// If present, sets CachingInodeOperationsOptions.LimitHostFDTranslation to
|
||||
// true.
|
||||
limitHostFDTranslationKey = "limit_host_fd_translation"
|
||||
)
|
||||
|
||||
// defaultAname is the default attach name.
|
||||
@@ -134,12 +138,13 @@ func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSou
|
||||
|
||||
// opts are parsed 9p mount options.
|
||||
type opts struct {
|
||||
fd int
|
||||
aname string
|
||||
policy cachePolicy
|
||||
msize uint32
|
||||
version string
|
||||
privateunixsocket bool
|
||||
fd int
|
||||
aname string
|
||||
policy cachePolicy
|
||||
msize uint32
|
||||
version string
|
||||
privateunixsocket bool
|
||||
limitHostFDTranslation bool
|
||||
}
|
||||
|
||||
// options parses mount(2) data into structured options.
|
||||
@@ -237,6 +242,11 @@ func options(data string) (opts, error) {
|
||||
delete(options, privateUnixSocketKey)
|
||||
}
|
||||
|
||||
if _, ok := options[limitHostFDTranslationKey]; ok {
|
||||
o.limitHostFDTranslation = true
|
||||
delete(options, limitHostFDTranslationKey)
|
||||
}
|
||||
|
||||
// Fail to attach if the caller wanted us to do something that we
|
||||
// don't support.
|
||||
if len(options) > 0 {
|
||||
|
||||
@@ -117,6 +117,11 @@ type session struct {
|
||||
// Flags provided to the mount.
|
||||
superBlockFlags fs.MountSourceFlags `state:"wait"`
|
||||
|
||||
// limitHostFDTranslation is the value used for
|
||||
// CachingInodeOperationsOptions.LimitHostFDTranslation for all
|
||||
// CachingInodeOperations created by the session.
|
||||
limitHostFDTranslation bool
|
||||
|
||||
// connID is a unique identifier for the session connection.
|
||||
connID string `state:"wait"`
|
||||
|
||||
@@ -218,8 +223,11 @@ func newInodeOperations(ctx context.Context, s *session, file contextFile, qid p
|
||||
|
||||
uattr := unstable(ctx, valid, attr, s.mounter, s.client)
|
||||
return sattr, &inodeOperations{
|
||||
fileState: fileState,
|
||||
cachingInodeOps: fsutil.NewCachingInodeOperations(ctx, fileState, uattr, s.superBlockFlags.ForcePageCache),
|
||||
fileState: fileState,
|
||||
cachingInodeOps: fsutil.NewCachingInodeOperations(ctx, fileState, uattr, fsutil.CachingInodeOperationsOptions{
|
||||
ForcePageCache: s.superBlockFlags.ForcePageCache,
|
||||
LimitHostFDTranslation: s.limitHostFDTranslation,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,13 +250,14 @@ func Root(ctx context.Context, dev string, filesystem fs.Filesystem, superBlockF
|
||||
|
||||
// Construct the session.
|
||||
s := session{
|
||||
connID: dev,
|
||||
msize: o.msize,
|
||||
version: o.version,
|
||||
cachePolicy: o.policy,
|
||||
aname: o.aname,
|
||||
superBlockFlags: superBlockFlags,
|
||||
mounter: mounter,
|
||||
connID: dev,
|
||||
msize: o.msize,
|
||||
version: o.version,
|
||||
cachePolicy: o.policy,
|
||||
aname: o.aname,
|
||||
superBlockFlags: superBlockFlags,
|
||||
limitHostFDTranslation: o.limitHostFDTranslation,
|
||||
mounter: mounter,
|
||||
}
|
||||
s.EnableLeakCheck("gofer.session")
|
||||
|
||||
|
||||
@@ -200,8 +200,10 @@ func newInode(ctx context.Context, msrc *fs.MountSource, fd int, saveable bool,
|
||||
// Build the fs.InodeOperations.
|
||||
uattr := unstableAttr(msrc.MountSourceOperations.(*superOperations), &s)
|
||||
iops := &inodeOperations{
|
||||
fileState: fileState,
|
||||
cachingInodeOps: fsutil.NewCachingInodeOperations(ctx, fileState, uattr, msrc.Flags.ForcePageCache),
|
||||
fileState: fileState,
|
||||
cachingInodeOps: fsutil.NewCachingInodeOperations(ctx, fileState, uattr, fsutil.CachingInodeOperationsOptions{
|
||||
ForcePageCache: msrc.Flags.ForcePageCache,
|
||||
}),
|
||||
}
|
||||
|
||||
// Return the fs.Inode.
|
||||
|
||||
Reference in New Issue
Block a user