mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Remove fs.Handle, ramfs.Entry, and all the DeprecatedFileOperations.
More helper structs have been added to the fsutil package to make it easier to implement fs.InodeOperations and fs.FileOperations. PiperOrigin-RevId: 229305982 Change-Id: Ib6f8d3862f4216745116857913dbfa351530223b
This commit is contained in:
committed by
Shentubot
parent
343ebe9789
commit
dc8450b567
@@ -22,8 +22,10 @@ const (
|
||||
DEVPTS_SUPER_MAGIC = 0x00001cd1
|
||||
OVERLAYFS_SUPER_MAGIC = 0x794c7630
|
||||
PIPEFS_MAGIC = 0x50495045
|
||||
PROC_SUPER_MAGIC = 0x9fa0
|
||||
RAMFS_MAGIC = 0x09041934
|
||||
SOCKFS_MAGIC = 0x534F434B
|
||||
SYSFS_MAGIC = 0x62656572
|
||||
TMPFS_MAGIC = 0x01021994
|
||||
V9FS_MAGIC = 0x01021997
|
||||
)
|
||||
|
||||
+2
-1
@@ -94,7 +94,8 @@ go_test(
|
||||
deps = [
|
||||
":fs",
|
||||
"//pkg/sentry/context",
|
||||
"//pkg/sentry/fs/ramfs/test",
|
||||
"//pkg/sentry/fs/fsutil",
|
||||
"//pkg/sentry/fs/ramfs",
|
||||
"//pkg/sentry/fs/tmpfs",
|
||||
"//pkg/sentry/kernel/contexttest",
|
||||
"//pkg/sentry/usermem",
|
||||
|
||||
@@ -28,16 +28,12 @@ import (
|
||||
// with any real filesystem. Some types depend on completely pseudo
|
||||
// "anon" inodes (eventfds, epollfds, etc).
|
||||
func NewInode(ctx context.Context) *fs.Inode {
|
||||
return fs.NewInode(fsutil.NewSimpleInodeOperations(fsutil.InodeSimpleAttributes{
|
||||
FSType: linux.ANON_INODE_FS_MAGIC,
|
||||
UAttr: fs.WithCurrentTime(ctx, fs.UnstableAttr{
|
||||
Owner: fs.FileOwnerFromContext(ctx),
|
||||
Perms: fs.FilePermissions{
|
||||
User: fs.PermMask{Read: true, Write: true},
|
||||
},
|
||||
Links: 1,
|
||||
}),
|
||||
}), fs.NewNonCachingMountSource(nil, fs.MountSourceFlags{}), fs.StableAttr{
|
||||
iops := &fsutil.SimpleFileInode{
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, fs.RootOwner, fs.FilePermissions{
|
||||
User: fs.PermMask{Read: true, Write: true},
|
||||
}, linux.ANON_INODE_FS_MAGIC),
|
||||
}
|
||||
return fs.NewInode(iops, fs.NewPseudoMountSource(), fs.StableAttr{
|
||||
Type: fs.Anonymous,
|
||||
DeviceID: PseudoDevice.DeviceID(),
|
||||
InodeID: PseudoDevice.NextIno(),
|
||||
|
||||
@@ -28,6 +28,7 @@ go_library(
|
||||
"//pkg/sentry/usage",
|
||||
"//pkg/sentry/usermem",
|
||||
"//pkg/syserror",
|
||||
"//pkg/waiter",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usage"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/syserror"
|
||||
"gvisor.googlesource.com/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -42,9 +43,10 @@ const (
|
||||
//
|
||||
// +stateify savable
|
||||
type Area struct {
|
||||
fsutil.NoFsync `state:"nosave"`
|
||||
fsutil.DeprecatedFileOperations `state:"nosave"`
|
||||
fsutil.NotDirReaddir `state:"nosave"`
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileNoFsync `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
|
||||
ad *Device
|
||||
|
||||
@@ -98,11 +100,6 @@ func (a *Area) Write(ctx context.Context, file *fs.File, src usermem.IOSequence,
|
||||
return 0, syserror.ENOSYS
|
||||
}
|
||||
|
||||
// Flush implements fs.FileOperations.Flush.
|
||||
func (a *Area) Flush(ctx context.Context, file *fs.File) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfigureMMap implements fs.FileOperations.ConfigureMMap.
|
||||
func (a *Area) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MMapOpts) error {
|
||||
a.mu.Lock()
|
||||
@@ -122,8 +119,7 @@ func (a *Area) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MM
|
||||
return syserror.ENOMEM
|
||||
}
|
||||
tmpfsInodeOps := tmpfs.NewInMemoryFile(ctx, usage.Tmpfs, fs.UnstableAttr{}, k)
|
||||
// This is not backed by a real filesystem, so we pass in nil.
|
||||
tmpfsInode := fs.NewInode(tmpfsInodeOps, fs.NewNonCachingMountSource(nil, fs.MountSourceFlags{}), fs.StableAttr{})
|
||||
tmpfsInode := fs.NewInode(tmpfsInodeOps, fs.NewPseudoMountSource(), fs.StableAttr{})
|
||||
dirent := fs.NewDirent(tmpfsInode, namePrefix+"/"+a.name)
|
||||
tmpfsFile, err := tmpfsInode.GetFile(ctx, dirent, fs.FileFlags{Read: true, Write: true})
|
||||
// Drop the extra reference on the Dirent.
|
||||
|
||||
+11
-122
@@ -16,49 +16,40 @@
|
||||
package ashmem
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
// Device implements fs.InodeOperations.
|
||||
//
|
||||
// +stateify savable
|
||||
type Device struct {
|
||||
fsutil.DeprecatedFileOperations `state:"nosave"`
|
||||
fsutil.InodeGenericChecker `state:"nosave"`
|
||||
fsutil.InodeNoExtendedAttributes `state:"nosave"`
|
||||
fsutil.InodeNoopRelease `state:"nosave"`
|
||||
fsutil.InodeNoopTruncate `state:"nosave"`
|
||||
fsutil.InodeNoopWriteOut `state:"nosave"`
|
||||
fsutil.InodeNotDirectory `state:"nosave"`
|
||||
fsutil.InodeNotRenameable `state:"nosave"`
|
||||
fsutil.InodeNotMappable `state:"nosave"`
|
||||
fsutil.InodeNotSocket `state:"nosave"`
|
||||
fsutil.InodeNotSymlink `state:"nosave"`
|
||||
fsutil.NoFsync `state:"nosave"`
|
||||
fsutil.NoMappable `state:"nosave"`
|
||||
fsutil.NoopWriteOut `state:"nosave"`
|
||||
fsutil.NotDirReaddir `state:"nosave"`
|
||||
fsutil.InodeVirtual `state:"nosave"`
|
||||
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
unstable fs.UnstableAttr
|
||||
fsutil.InodeSimpleAttributes
|
||||
}
|
||||
|
||||
var _ fs.InodeOperations = (*Device)(nil)
|
||||
|
||||
// NewDevice creates and intializes a Device structure.
|
||||
func NewDevice(ctx context.Context, owner fs.FileOwner, fp fs.FilePermissions) *Device {
|
||||
return &Device{
|
||||
unstable: fs.WithCurrentTime(ctx, fs.UnstableAttr{
|
||||
Owner: owner,
|
||||
Perms: fp,
|
||||
Links: 1,
|
||||
}),
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fp, linux.ANON_INODE_FS_MAGIC),
|
||||
}
|
||||
}
|
||||
|
||||
// Release implements fs.InodeOperations.Release.
|
||||
func (ad *Device) Release(context.Context) {}
|
||||
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
func (ad *Device) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
return fs.NewFile(ctx, d, flags, &Area{
|
||||
@@ -67,105 +58,3 @@ func (ad *Device) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags)
|
||||
perms: usermem.AnyAccess,
|
||||
}), nil
|
||||
}
|
||||
|
||||
// UnstableAttr implements fs.InodeOperations.UnstableAttr.
|
||||
func (ad *Device) UnstableAttr(ctx context.Context, inode *fs.Inode) (fs.UnstableAttr, error) {
|
||||
ad.mu.Lock()
|
||||
defer ad.mu.Unlock()
|
||||
return ad.unstable, nil
|
||||
}
|
||||
|
||||
// Check implements fs.InodeOperations.Check.
|
||||
func (ad *Device) Check(ctx context.Context, inode *fs.Inode, p fs.PermMask) bool {
|
||||
return fs.ContextCanAccessFile(ctx, inode, p)
|
||||
}
|
||||
|
||||
// SetPermissions implements fs.InodeOperations.SetPermissions.
|
||||
func (ad *Device) SetPermissions(ctx context.Context, inode *fs.Inode, fp fs.FilePermissions) bool {
|
||||
ad.mu.Lock()
|
||||
defer ad.mu.Unlock()
|
||||
ad.unstable.Perms = fp
|
||||
ad.unstable.StatusChangeTime = time.NowFromContext(ctx)
|
||||
return true
|
||||
}
|
||||
|
||||
// SetOwner implements fs.InodeOperations.SetOwner.
|
||||
func (ad *Device) SetOwner(ctx context.Context, inode *fs.Inode, owner fs.FileOwner) error {
|
||||
ad.mu.Lock()
|
||||
defer ad.mu.Unlock()
|
||||
if owner.UID.Ok() {
|
||||
ad.unstable.Owner.UID = owner.UID
|
||||
}
|
||||
if owner.GID.Ok() {
|
||||
ad.unstable.Owner.GID = owner.GID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTimestamps implements fs.InodeOperations.SetTimestamps.
|
||||
func (ad *Device) SetTimestamps(ctx context.Context, inode *fs.Inode, ts fs.TimeSpec) error {
|
||||
if ts.ATimeOmit && ts.MTimeOmit {
|
||||
return nil
|
||||
}
|
||||
|
||||
ad.mu.Lock()
|
||||
defer ad.mu.Unlock()
|
||||
|
||||
now := time.NowFromContext(ctx)
|
||||
if !ts.ATimeOmit {
|
||||
if ts.ATimeSetSystemTime {
|
||||
ad.unstable.AccessTime = now
|
||||
} else {
|
||||
ad.unstable.AccessTime = ts.ATime
|
||||
}
|
||||
}
|
||||
if !ts.MTimeOmit {
|
||||
if ts.MTimeSetSystemTime {
|
||||
ad.unstable.ModificationTime = now
|
||||
} else {
|
||||
ad.unstable.ModificationTime = ts.MTime
|
||||
}
|
||||
}
|
||||
ad.unstable.StatusChangeTime = now
|
||||
return nil
|
||||
}
|
||||
|
||||
// Truncate implements fs.InodeOperations.WriteOut.
|
||||
//
|
||||
// Ignored by ashmem.
|
||||
func (ad *Device) Truncate(ctx context.Context, inode *fs.Inode, size int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLink implements fs.InodeOperations.AddLink.
|
||||
//
|
||||
// Ashmem doesn't support links, no-op.
|
||||
func (ad *Device) AddLink() {}
|
||||
|
||||
// DropLink implements fs.InodeOperations.DropLink.
|
||||
//
|
||||
// Ashmem doesn't support links, no-op.
|
||||
func (ad *Device) DropLink() {}
|
||||
|
||||
// NotifyStatusChange implements fs.InodeOperations.NotifyStatusChange.
|
||||
func (ad *Device) NotifyStatusChange(ctx context.Context) {
|
||||
ad.mu.Lock()
|
||||
defer ad.mu.Unlock()
|
||||
now := time.NowFromContext(ctx)
|
||||
ad.unstable.ModificationTime = now
|
||||
ad.unstable.StatusChangeTime = now
|
||||
}
|
||||
|
||||
// IsVirtual implements fs.InodeOperations.IsVirtual.
|
||||
//
|
||||
// Ashmem is virtual.
|
||||
func (ad *Device) IsVirtual() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// StatFS implements fs.InodeOperations.StatFS.
|
||||
//
|
||||
// Ashmem doesn't support querying for filesystem info.
|
||||
func (ad *Device) StatFS(context.Context) (fs.Info, error) {
|
||||
return fs.Info{}, syserror.ENOSYS
|
||||
}
|
||||
|
||||
@@ -180,6 +180,53 @@ type UnstableAttr struct {
|
||||
Links uint64
|
||||
}
|
||||
|
||||
// SetOwner sets the owner and group if they are valid.
|
||||
//
|
||||
// This method is NOT thread-safe. Callers must prevent concurrent calls.
|
||||
func (ua *UnstableAttr) SetOwner(ctx context.Context, owner FileOwner) {
|
||||
if owner.UID.Ok() {
|
||||
ua.Owner.UID = owner.UID
|
||||
}
|
||||
if owner.GID.Ok() {
|
||||
ua.Owner.GID = owner.GID
|
||||
}
|
||||
ua.StatusChangeTime = ktime.NowFromContext(ctx)
|
||||
}
|
||||
|
||||
// SetPermissions sets the permissions.
|
||||
//
|
||||
// This method is NOT thread-safe. Callers must prevent concurrent calls.
|
||||
func (ua *UnstableAttr) SetPermissions(ctx context.Context, p FilePermissions) {
|
||||
ua.Perms = p
|
||||
ua.StatusChangeTime = ktime.NowFromContext(ctx)
|
||||
}
|
||||
|
||||
// SetTimestamps sets the timestamps according to the TimeSpec.
|
||||
//
|
||||
// This method is NOT thread-safe. Callers must prevent concurrent calls.
|
||||
func (ua *UnstableAttr) SetTimestamps(ctx context.Context, ts TimeSpec) {
|
||||
if ts.ATimeOmit && ts.MTimeOmit {
|
||||
return
|
||||
}
|
||||
|
||||
now := ktime.NowFromContext(ctx)
|
||||
if !ts.ATimeOmit {
|
||||
if ts.ATimeSetSystemTime {
|
||||
ua.AccessTime = now
|
||||
} else {
|
||||
ua.AccessTime = ts.ATime
|
||||
}
|
||||
}
|
||||
if !ts.MTimeOmit {
|
||||
if ts.MTimeSetSystemTime {
|
||||
ua.ModificationTime = now
|
||||
} else {
|
||||
ua.ModificationTime = ts.MTime
|
||||
}
|
||||
}
|
||||
ua.StatusChangeTime = now
|
||||
}
|
||||
|
||||
// WithCurrentTime returns u with AccessTime == ModificationTime == current time.
|
||||
func WithCurrentTime(ctx context.Context, u UnstableAttr) UnstableAttr {
|
||||
t := ktime.NowFromContext(ctx)
|
||||
|
||||
@@ -16,11 +16,11 @@ go_library(
|
||||
"//pkg/sentry/fs",
|
||||
"//pkg/sentry/fs/fsutil",
|
||||
"//pkg/sentry/kernel",
|
||||
"//pkg/sentry/kernel/time",
|
||||
"//pkg/sentry/memmap",
|
||||
"//pkg/sentry/platform",
|
||||
"//pkg/sentry/usage",
|
||||
"//pkg/sentry/usermem",
|
||||
"//pkg/syserror",
|
||||
"//pkg/waiter",
|
||||
],
|
||||
)
|
||||
|
||||
+14
-121
@@ -24,12 +24,12 @@ import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/time"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/memmap"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usage"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/syserror"
|
||||
"gvisor.googlesource.com/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -43,34 +43,29 @@ const (
|
||||
//
|
||||
// +stateify savable
|
||||
type Device struct {
|
||||
fsutil.InodeGenericChecker `state:"nosave"`
|
||||
fsutil.InodeNoExtendedAttributes `state:"nosave"`
|
||||
fsutil.InodeNoopRelease `state:"nosave"`
|
||||
fsutil.InodeNoopTruncate `state:"nosave"`
|
||||
fsutil.InodeNoopWriteOut `state:"nosave"`
|
||||
fsutil.InodeNotDirectory `state:"nosave"`
|
||||
fsutil.InodeNotRenameable `state:"nosave"`
|
||||
fsutil.InodeNotMappable `state:"nosave"`
|
||||
fsutil.InodeNotSocket `state:"nosave"`
|
||||
fsutil.InodeNotSymlink `state:"nosave"`
|
||||
fsutil.NoMappable `state:"nosave"`
|
||||
fsutil.NoopWriteOut `state:"nosave"`
|
||||
fsutil.DeprecatedFileOperations `state:"nosave"`
|
||||
fsutil.InodeVirtual `state:"nosave"`
|
||||
|
||||
// mu protects unstable.
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
unstable fs.UnstableAttr
|
||||
fsutil.InodeSimpleAttributes
|
||||
}
|
||||
|
||||
var _ fs.InodeOperations = (*Device)(nil)
|
||||
|
||||
// NewDevice creates and intializes a Device structure.
|
||||
func NewDevice(ctx context.Context, owner fs.FileOwner, fp fs.FilePermissions) *Device {
|
||||
return &Device{
|
||||
unstable: fs.WithCurrentTime(ctx, fs.UnstableAttr{
|
||||
Owner: owner,
|
||||
Perms: fp,
|
||||
Links: 1,
|
||||
}),
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fp, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Release implements fs.InodeOperations.Release.
|
||||
func (bd *Device) Release(context.Context) {}
|
||||
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
//
|
||||
// TODO: Add functionality to GetFile: Additional fields will be
|
||||
@@ -85,115 +80,13 @@ func (bd *Device) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags)
|
||||
}), nil
|
||||
}
|
||||
|
||||
// UnstableAttr implements fs.InodeOperations.UnstableAttr.
|
||||
func (bd *Device) UnstableAttr(ctx context.Context, inode *fs.Inode) (fs.UnstableAttr, error) {
|
||||
bd.mu.Lock()
|
||||
defer bd.mu.Unlock()
|
||||
return bd.unstable, nil
|
||||
}
|
||||
|
||||
// Check implements fs.InodeOperations.Check.
|
||||
func (bd *Device) Check(ctx context.Context, inode *fs.Inode, p fs.PermMask) bool {
|
||||
return fs.ContextCanAccessFile(ctx, inode, p)
|
||||
}
|
||||
|
||||
// SetPermissions implements fs.InodeOperations.SetPermissions.
|
||||
func (bd *Device) SetPermissions(ctx context.Context, inode *fs.Inode, fp fs.FilePermissions) bool {
|
||||
bd.mu.Lock()
|
||||
defer bd.mu.Unlock()
|
||||
bd.unstable.Perms = fp
|
||||
bd.unstable.StatusChangeTime = time.NowFromContext(ctx)
|
||||
return true
|
||||
}
|
||||
|
||||
// SetOwner implements fs.InodeOperations.SetOwner.
|
||||
func (bd *Device) SetOwner(ctx context.Context, inode *fs.Inode, owner fs.FileOwner) error {
|
||||
bd.mu.Lock()
|
||||
defer bd.mu.Unlock()
|
||||
if owner.UID.Ok() {
|
||||
bd.unstable.Owner.UID = owner.UID
|
||||
}
|
||||
if owner.GID.Ok() {
|
||||
bd.unstable.Owner.GID = owner.GID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTimestamps implements fs.InodeOperations.SetTimestamps.
|
||||
func (bd *Device) SetTimestamps(ctx context.Context, inode *fs.Inode, ts fs.TimeSpec) error {
|
||||
if ts.ATimeOmit && ts.MTimeOmit {
|
||||
return nil
|
||||
}
|
||||
|
||||
bd.mu.Lock()
|
||||
defer bd.mu.Unlock()
|
||||
|
||||
now := time.NowFromContext(ctx)
|
||||
if !ts.ATimeOmit {
|
||||
if ts.ATimeSetSystemTime {
|
||||
bd.unstable.AccessTime = now
|
||||
} else {
|
||||
bd.unstable.AccessTime = ts.ATime
|
||||
}
|
||||
}
|
||||
if !ts.MTimeOmit {
|
||||
if ts.MTimeSetSystemTime {
|
||||
bd.unstable.ModificationTime = now
|
||||
} else {
|
||||
bd.unstable.ModificationTime = ts.MTime
|
||||
}
|
||||
}
|
||||
bd.unstable.StatusChangeTime = now
|
||||
return nil
|
||||
}
|
||||
|
||||
// Truncate implements fs.InodeOperations.WriteOut.
|
||||
//
|
||||
// Ignored for a character device, such as Binder.
|
||||
func (bd *Device) Truncate(ctx context.Context, inode *fs.Inode, size int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddLink implements fs.InodeOperations.AddLink.
|
||||
//
|
||||
// Binder doesn't support links, no-op.
|
||||
func (bd *Device) AddLink() {}
|
||||
|
||||
// DropLink implements fs.InodeOperations.DropLink.
|
||||
//
|
||||
// Binder doesn't support links, no-op.
|
||||
func (bd *Device) DropLink() {}
|
||||
|
||||
// NotifyStatusChange implements fs.InodeOperations.NotifyStatusChange.
|
||||
func (bd *Device) NotifyStatusChange(ctx context.Context) {
|
||||
bd.mu.Lock()
|
||||
defer bd.mu.Unlock()
|
||||
now := time.NowFromContext(ctx)
|
||||
bd.unstable.ModificationTime = now
|
||||
bd.unstable.StatusChangeTime = now
|
||||
}
|
||||
|
||||
// IsVirtual implements fs.InodeOperations.IsVirtual.
|
||||
//
|
||||
// Binder is virtual.
|
||||
func (bd *Device) IsVirtual() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// StatFS implements fs.InodeOperations.StatFS.
|
||||
//
|
||||
// Binder doesn't support querying for filesystem info.
|
||||
func (bd *Device) StatFS(context.Context) (fs.Info, error) {
|
||||
return fs.Info{}, syserror.ENOSYS
|
||||
}
|
||||
|
||||
// Proc implements fs.FileOperations and fs.IoctlGetter.
|
||||
//
|
||||
// +stateify savable
|
||||
type Proc struct {
|
||||
fsutil.NoFsync `state:"nosave"`
|
||||
fsutil.DeprecatedFileOperations `state:"nosave"`
|
||||
fsutil.NotDirReaddir `state:"nosave"`
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileNoFsync `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
|
||||
bd *Device
|
||||
task *kernel.Task
|
||||
|
||||
@@ -32,5 +32,6 @@ go_library(
|
||||
"//pkg/sentry/safemem",
|
||||
"//pkg/sentry/usermem",
|
||||
"//pkg/syserror",
|
||||
"//pkg/waiter",
|
||||
],
|
||||
)
|
||||
|
||||
+14
-15
@@ -16,6 +16,8 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ashmem"
|
||||
@@ -26,13 +28,6 @@ import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
)
|
||||
|
||||
// Dev is the root node.
|
||||
//
|
||||
// +stateify savable
|
||||
type Dev struct {
|
||||
ramfs.Dir
|
||||
}
|
||||
|
||||
func newCharacterDevice(iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode {
|
||||
return fs.NewInode(iops, msrc, fs.StableAttr{
|
||||
DeviceID: devDevice.DeviceID(),
|
||||
@@ -43,8 +38,7 @@ func newCharacterDevice(iops fs.InodeOperations, msrc *fs.MountSource) *fs.Inode
|
||||
}
|
||||
|
||||
func newDirectory(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
|
||||
iops := &ramfs.Dir{}
|
||||
iops.InitDir(ctx, map[string]*fs.Inode{}, fs.RootOwner, fs.FilePermsFromMode(0555))
|
||||
iops := ramfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0555))
|
||||
return fs.NewInode(iops, msrc, fs.StableAttr{
|
||||
DeviceID: devDevice.DeviceID(),
|
||||
InodeID: devDevice.NextIno(),
|
||||
@@ -54,8 +48,7 @@ func newDirectory(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
|
||||
}
|
||||
|
||||
func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.Inode {
|
||||
iops := &ramfs.Symlink{}
|
||||
iops.InitSymlink(ctx, fs.RootOwner, target)
|
||||
iops := ramfs.NewSymlink(ctx, fs.RootOwner, target)
|
||||
return fs.NewInode(iops, msrc, fs.StableAttr{
|
||||
DeviceID: devDevice.DeviceID(),
|
||||
InodeID: devDevice.NextIno(),
|
||||
@@ -66,8 +59,6 @@ func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.In
|
||||
|
||||
// New returns the root node of a device filesystem.
|
||||
func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEnabled bool) *fs.Inode {
|
||||
d := &Dev{}
|
||||
|
||||
contents := map[string]*fs.Inode{
|
||||
"fd": newSymlink(ctx, "/proc/self/fd", msrc),
|
||||
"stdin": newSymlink(ctx, "/proc/self/fd/0", msrc),
|
||||
@@ -114,11 +105,19 @@ func New(ctx context.Context, msrc *fs.MountSource, binderEnabled bool, ashmemEn
|
||||
contents["ashmem"] = newCharacterDevice(ashmem, msrc)
|
||||
}
|
||||
|
||||
d.InitDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555))
|
||||
return fs.NewInode(d, msrc, fs.StableAttr{
|
||||
iops := ramfs.NewDir(ctx, contents, fs.RootOwner, fs.FilePermsFromMode(0555))
|
||||
return fs.NewInode(iops, msrc, fs.StableAttr{
|
||||
DeviceID: devDevice.DeviceID(),
|
||||
InodeID: devDevice.NextIno(),
|
||||
BlockSize: usermem.PageSize,
|
||||
Type: fs.Directory,
|
||||
})
|
||||
}
|
||||
|
||||
// readZeros implements fs.FileOperations.Read with infinite null bytes.
|
||||
type readZeros struct{}
|
||||
|
||||
// Read implements fs.FileOperations.Read.
|
||||
func (readZeros) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
|
||||
return dst.ZeroOut(ctx, math.MaxInt64)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@ const ashmemEnabledKey = "ashmem_enabled"
|
||||
// +stateify savable
|
||||
type filesystem struct{}
|
||||
|
||||
var _ fs.Filesystem = (*filesystem)(nil)
|
||||
|
||||
func init() {
|
||||
fs.RegisterFilesystem(&filesystem{})
|
||||
}
|
||||
|
||||
+42
-19
@@ -15,41 +15,64 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/syserror"
|
||||
"gvisor.googlesource.com/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
// fullDevice is used to implement /dev/full.
|
||||
//
|
||||
// +stateify savable
|
||||
type fullDevice struct {
|
||||
ramfs.Entry
|
||||
fsutil.InodeGenericChecker `state:"nosave"`
|
||||
fsutil.InodeNoExtendedAttributes `state:"nosave"`
|
||||
fsutil.InodeNoopRelease `state:"nosave"`
|
||||
fsutil.InodeNoopTruncate `state:"nosave"`
|
||||
fsutil.InodeNoopWriteOut `state:"nosave"`
|
||||
fsutil.InodeNotDirectory `state:"nosave"`
|
||||
fsutil.InodeNotMappable `state:"nosave"`
|
||||
fsutil.InodeNotSocket `state:"nosave"`
|
||||
fsutil.InodeNotSymlink `state:"nosave"`
|
||||
fsutil.InodeVirtual `state:"nosave"`
|
||||
|
||||
fsutil.InodeSimpleAttributes
|
||||
}
|
||||
|
||||
var _ fs.InodeOperations = (*fullDevice)(nil)
|
||||
|
||||
func newFullDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *fullDevice {
|
||||
f := &fullDevice{}
|
||||
f.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
|
||||
f := &fullDevice{
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// DeprecatedPwritev implements fs.InodeOperations.DeprecatedPwritev by
|
||||
// returining ENOSPC.
|
||||
func (f *fullDevice) DeprecatedPwritev(_ context.Context, _ usermem.IOSequence, _ int64) (int64, error) {
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
func (f *fullDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
flags.Pread = true
|
||||
return fs.NewFile(ctx, dirent, flags, &fullFileOperations{}), nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type fullFileOperations struct {
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileGenericSeek `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
fsutil.FileNoMMap `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoopFsync `state:"nosave"`
|
||||
fsutil.FileNoopRelease `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
readZeros `state:"nosave"`
|
||||
}
|
||||
|
||||
var _ fs.FileOperations = (*fullFileOperations)(nil)
|
||||
|
||||
// Write implements FileOperations.Write.
|
||||
func (fullFileOperations) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
|
||||
return 0, syserror.ENOSPC
|
||||
}
|
||||
|
||||
// DeprecatedPreadv implements fs.InodeOperations.DeprecatedPreadv.
|
||||
func (f *fullDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, _ int64) (int64, error) {
|
||||
return dst.ZeroOut(ctx, math.MaxInt64)
|
||||
}
|
||||
|
||||
// Truncate should be simply ignored for character devices on linux.
|
||||
func (f *fullDevice) Truncate(context.Context, *fs.Inode, int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+57
-31
@@ -15,78 +15,104 @@
|
||||
package dev
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/memmap"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/mm"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/platform"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type nullDevice struct {
|
||||
ramfs.Entry
|
||||
fsutil.InodeGenericChecker `state:"nosave"`
|
||||
fsutil.InodeNoExtendedAttributes `state:"nosave"`
|
||||
fsutil.InodeNoopRelease `state:"nosave"`
|
||||
fsutil.InodeNoopTruncate `state:"nosave"`
|
||||
fsutil.InodeNoopWriteOut `state:"nosave"`
|
||||
fsutil.InodeNotDirectory `state:"nosave"`
|
||||
fsutil.InodeNotMappable `state:"nosave"`
|
||||
fsutil.InodeNotSocket `state:"nosave"`
|
||||
fsutil.InodeNotSymlink `state:"nosave"`
|
||||
fsutil.InodeVirtual `state:"nosave"`
|
||||
|
||||
fsutil.InodeSimpleAttributes
|
||||
}
|
||||
|
||||
var _ fs.InodeOperations = (*nullDevice)(nil)
|
||||
|
||||
func newNullDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *nullDevice {
|
||||
n := &nullDevice{}
|
||||
n.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
|
||||
n := &nullDevice{
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// DeprecatedPreadv reads data from the device.
|
||||
func (n *nullDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
|
||||
return 0, io.EOF
|
||||
// GetFile implements fs.FileOperations.GetFile.
|
||||
func (n *nullDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
flags.Pread = true
|
||||
flags.Pwrite = true
|
||||
|
||||
return fs.NewFile(ctx, dirent, flags, &nullFileOperations{}), nil
|
||||
}
|
||||
|
||||
// DeprecatedPwritev discards writes.
|
||||
func (n *nullDevice) DeprecatedPwritev(_ context.Context, src usermem.IOSequence, offset int64) (int64, error) {
|
||||
return src.NumBytes(), nil
|
||||
// +stateify savable
|
||||
type nullFileOperations struct {
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileGenericSeek `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
fsutil.FileNoMMap `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoopFsync `state:"nosave"`
|
||||
fsutil.FileNoopRead `state:"nosave"`
|
||||
fsutil.FileNoopWrite `state:"nosave"`
|
||||
fsutil.FileNoopRelease `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
}
|
||||
|
||||
// Truncate should be simply ignored for character devices on linux.
|
||||
func (n *nullDevice) Truncate(context.Context, *fs.Inode, int64) error {
|
||||
return nil
|
||||
}
|
||||
var _ fs.FileOperations = (*nullFileOperations)(nil)
|
||||
|
||||
// +stateify savable
|
||||
type zeroDevice struct {
|
||||
nullDevice
|
||||
}
|
||||
|
||||
var _ fs.InodeOperations = (*zeroDevice)(nil)
|
||||
|
||||
func newZeroDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *zeroDevice {
|
||||
zd := &zeroDevice{}
|
||||
zd.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
|
||||
zd := &zeroDevice{
|
||||
nullDevice: nullDevice{
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
|
||||
},
|
||||
}
|
||||
return zd
|
||||
}
|
||||
|
||||
// DeprecatedPreadv implements fs.InodeOperations.DeprecatedPreadv.
|
||||
func (zd *zeroDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
|
||||
return dst.ZeroOut(ctx, math.MaxInt64)
|
||||
}
|
||||
|
||||
// GetFile overrides ramfs.Entry.GetFile and returns a zeroFile instead.
|
||||
// GetFile implements fs.FileOperations.GetFile.
|
||||
func (zd *zeroDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
// Allow pread(2) and pwrite(2) on this file.
|
||||
flags.Pread = true
|
||||
flags.Pwrite = true
|
||||
|
||||
return fs.NewFile(ctx, dirent, flags, &zeroFileOperations{
|
||||
FileOperations: &fsutil.Handle{HandleOperations: dirent.Inode.HandleOps()},
|
||||
}), nil
|
||||
return fs.NewFile(ctx, dirent, flags, &zeroFileOperations{}), nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type zeroFileOperations struct {
|
||||
fs.FileOperations
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileGenericSeek `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoopFsync `state:"nosave"`
|
||||
fsutil.FileNoopRelease `state:"nosave"`
|
||||
fsutil.FileNoopWrite `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
readZeros `state:"nosave"`
|
||||
}
|
||||
|
||||
var _ fs.FileOperations = (*zeroFileOperations)(nil)
|
||||
|
||||
// ConfigureMMap implements fs.FileOperations.ConfigureMMap.
|
||||
func (*zeroFileOperations) ConfigureMMap(ctx context.Context, file *fs.File, opts *memmap.MMapOpts) error {
|
||||
m, err := mm.NewSharedAnonMappable(opts.Length, platform.FromContext(ctx))
|
||||
|
||||
+41
-20
@@ -19,37 +19,58 @@ import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/rand"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/safemem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
|
||||
"gvisor.googlesource.com/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type randomDevice struct {
|
||||
ramfs.Entry
|
||||
fsutil.InodeGenericChecker `state:"nosave"`
|
||||
fsutil.InodeNoExtendedAttributes `state:"nosave"`
|
||||
fsutil.InodeNoopRelease `state:"nosave"`
|
||||
fsutil.InodeNoopTruncate `state:"nosave"`
|
||||
fsutil.InodeNoopWriteOut `state:"nosave"`
|
||||
fsutil.InodeNotDirectory `state:"nosave"`
|
||||
fsutil.InodeNotMappable `state:"nosave"`
|
||||
fsutil.InodeNotSocket `state:"nosave"`
|
||||
fsutil.InodeNotSymlink `state:"nosave"`
|
||||
fsutil.InodeVirtual `state:"nosave"`
|
||||
|
||||
fsutil.InodeSimpleAttributes
|
||||
}
|
||||
|
||||
var _ fs.InodeOperations = (*randomDevice)(nil)
|
||||
|
||||
func newRandomDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMode) *randomDevice {
|
||||
r := &randomDevice{}
|
||||
r.InitEntry(ctx, owner, fs.FilePermsFromMode(mode))
|
||||
r := &randomDevice{
|
||||
InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(mode), linux.TMPFS_MAGIC),
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// DeprecatedPreadv reads random data.
|
||||
func (*randomDevice) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
|
||||
// GetFile implements fs.InodeOperations.GetFile.
|
||||
func (randomDevice) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
|
||||
return fs.NewFile(ctx, dirent, flags, &randomFileOperations{}), nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type randomFileOperations struct {
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileGenericSeek `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
fsutil.FileNoMMap `state:"nosave"`
|
||||
fsutil.FileNoopFsync `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
fsutil.FileNoopRelease `state:"nosave"`
|
||||
fsutil.FileNoopWrite `state:"nosave"`
|
||||
}
|
||||
|
||||
var _ fs.FileOperations = (*randomFileOperations)(nil)
|
||||
|
||||
// Read implements fs.FileOperations.Read.
|
||||
func (randomFileOperations) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, _ int64) (int64, error) {
|
||||
return dst.CopyOutFrom(ctx, safemem.FromIOReader{rand.Reader})
|
||||
}
|
||||
|
||||
// DeprecatedPwritev implements fs.HandleOperations.DeprecatedPwritev.
|
||||
func (*randomDevice) DeprecatedPwritev(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
|
||||
// On Linux, "Writing to /dev/random or /dev/urandom will update the
|
||||
// entropy pool with the data written, but this will not result in a higher
|
||||
// entropy count" - random(4). We don't need to support this, but we do
|
||||
// need to support the write, so just make it a no-op a la /dev/null.
|
||||
return src.NumBytes(), nil
|
||||
}
|
||||
|
||||
// Truncate should be simply ignored for character devices on linux.
|
||||
func (r *randomDevice) Truncate(context.Context, *fs.Inode, int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -837,8 +837,8 @@ func (d *Dirent) CreateFifo(ctx context.Context, root *Dirent, name string, perm
|
||||
})
|
||||
}
|
||||
|
||||
// getDotAttrs returns the DentAttrs corresponding to "." and ".." directories.
|
||||
func (d *Dirent) getDotAttrs(root *Dirent) (DentAttr, DentAttr) {
|
||||
// GetDotAttrs returns the DentAttrs corresponding to "." and ".." directories.
|
||||
func (d *Dirent) GetDotAttrs(root *Dirent) (DentAttr, DentAttr) {
|
||||
// Get '.'.
|
||||
sattr := d.Inode.StableAttr
|
||||
dot := DentAttr{
|
||||
@@ -870,7 +870,7 @@ func (d *Dirent) readdirFrozen(root *Dirent, offset int64, dirCtx *DirCtx) (int6
|
||||
// Collect attrs for "." and "..".
|
||||
attrs := make(map[string]DentAttr)
|
||||
names := []string{".", ".."}
|
||||
attrs["."], attrs[".."] = d.getDotAttrs(root)
|
||||
attrs["."], attrs[".."] = d.GetDotAttrs(root)
|
||||
|
||||
// Get info from all children.
|
||||
d.mu.Lock()
|
||||
@@ -965,7 +965,7 @@ func direntReaddir(ctx context.Context, d *Dirent, it DirIterator, root *Dirent,
|
||||
}
|
||||
|
||||
// Collect attrs for "." and "..".
|
||||
dot, dotdot := d.getDotAttrs(root)
|
||||
dot, dotdot := d.GetDotAttrs(root)
|
||||
|
||||
// Emit "." and ".." if the offset is low enough.
|
||||
if offset == 0 {
|
||||
|
||||
@@ -37,13 +37,13 @@ import (
|
||||
//
|
||||
// +stateify savable
|
||||
type pipeOperations struct {
|
||||
fsutil.PipeSeek `state:"nosave"`
|
||||
fsutil.NotDirReaddir `state:"nosave"`
|
||||
fsutil.NoFsync `state:"nosave"`
|
||||
fsutil.NoopFlush `state:"nosave"`
|
||||
fsutil.NoMMap `state:"nosave"`
|
||||
fsutil.NoIoctl `state:"nosave"`
|
||||
waiter.Queue `state:"nosave"`
|
||||
fsutil.FilePipeSeek `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
fsutil.FileNoFsync `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoMMap `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
waiter.Queue `state:"nosave"`
|
||||
|
||||
// flags are the flags used to open the pipe.
|
||||
flags fs.FileFlags `state:".(fs.FileFlags)"`
|
||||
|
||||
@@ -91,7 +91,7 @@ type FileOperations interface {
|
||||
Flush(ctx context.Context, file *File) error
|
||||
|
||||
// ConfigureMMap mutates opts to implement mmap(2) for the file. Most
|
||||
// implementations can either embed fsutil.NoMMap (if they don't support
|
||||
// implementations can either embed fsutil.FileNoMMap (if they don't support
|
||||
// memory mapping) or call fsutil.GenericConfigureMMap with the appropriate
|
||||
// memmap.Mappable.
|
||||
ConfigureMMap(ctx context.Context, file *File, opts *memmap.MMapOpts) error
|
||||
|
||||
@@ -20,7 +20,8 @@ import (
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
ramfstest "gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs/test"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs/ramfs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel/contexttest"
|
||||
)
|
||||
|
||||
@@ -135,7 +136,7 @@ func TestReaddirRevalidation(t *testing.T) {
|
||||
|
||||
// Get a handle to the dirent in the upper filesystem so that we can
|
||||
// modify it without going through the dirent.
|
||||
upperDir := upper.InodeOperations.(*dir).InodeOperations.(*ramfstest.Dir)
|
||||
upperDir := upper.InodeOperations.(*dir).InodeOperations.(*ramfs.Dir)
|
||||
|
||||
// Check that overlay returns the files from both upper and lower.
|
||||
openDir, err := overlay.GetFile(ctx, fs.NewDirent(overlay, "stub"), fs.FileFlags{Read: true})
|
||||
@@ -155,7 +156,7 @@ func TestReaddirRevalidation(t *testing.T) {
|
||||
if err := upperDir.Remove(ctx, upper, "a"); err != nil {
|
||||
t.Fatalf("error removing child: %v", err)
|
||||
}
|
||||
upperDir.AddChild(ctx, "c", fs.NewInode(ramfstest.NewFile(ctx, fs.FilePermissions{}),
|
||||
upperDir.AddChild(ctx, "c", fs.NewInode(fsutil.NewSimpleFileInode(ctx, fs.RootOwner, fs.FilePermissions{}, 0),
|
||||
upper.MountSource, fs.StableAttr{Type: fs.RegularFile}))
|
||||
|
||||
// Seek to beginning of the directory and do the readdir again.
|
||||
|
||||
@@ -31,14 +31,14 @@ import (
|
||||
// TestFileOperations is an implementation of the File interface. It provides all
|
||||
// required methods.
|
||||
type TestFileOperations struct {
|
||||
fsutil.NoopRelease `state:"nosave"`
|
||||
fsutil.PipeSeek `state:"nosave"`
|
||||
fsutil.NotDirReaddir `state:"nosave"`
|
||||
fsutil.NoFsync `state:"nosave"`
|
||||
fsutil.NoopFlush `state:"nosave"`
|
||||
fsutil.NoMMap `state:"nosave"`
|
||||
fsutil.NoIoctl `state:"nosave"`
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
fsutil.FileNoopRelease `state:"nosave"`
|
||||
fsutil.FilePipeSeek `state:"nosave"`
|
||||
fsutil.FileNotDirReaddir `state:"nosave"`
|
||||
fsutil.FileNoFsync `state:"nosave"`
|
||||
fsutil.FileNoopFlush `state:"nosave"`
|
||||
fsutil.FileNoMMap `state:"nosave"`
|
||||
fsutil.FileNoIoctl `state:"nosave"`
|
||||
waiter.AlwaysReady `state:"nosave"`
|
||||
}
|
||||
|
||||
// NewTestFile creates and initializes a new test file.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user