Add basic stateify annotations.
Updates #1663 PiperOrigin-RevId: 333539293
This commit is contained in:
parent
5d50c91c4d
commit
0a7075f38a
|
@ -24,6 +24,8 @@ import (
|
|||
const fullDevMinor = 7
|
||||
|
||||
// fullDevice implements vfs.Device for /dev/full.
|
||||
//
|
||||
// +stateify savable
|
||||
type fullDevice struct{}
|
||||
|
||||
// Open implements vfs.Device.Open.
|
||||
|
@ -38,6 +40,8 @@ func (fullDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, op
|
|||
}
|
||||
|
||||
// fullFD implements vfs.FileDescriptionImpl for /dev/full.
|
||||
//
|
||||
// +stateify savable
|
||||
type fullFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -25,6 +25,8 @@ import (
|
|||
const nullDevMinor = 3
|
||||
|
||||
// nullDevice implements vfs.Device for /dev/null.
|
||||
//
|
||||
// +stateify savable
|
||||
type nullDevice struct{}
|
||||
|
||||
// Open implements vfs.Device.Open.
|
||||
|
@ -39,6 +41,8 @@ func (nullDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, op
|
|||
}
|
||||
|
||||
// nullFD implements vfs.FileDescriptionImpl for /dev/null.
|
||||
//
|
||||
// +stateify savable
|
||||
type nullFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -30,6 +30,8 @@ const (
|
|||
)
|
||||
|
||||
// randomDevice implements vfs.Device for /dev/random and /dev/urandom.
|
||||
//
|
||||
// +stateify savable
|
||||
type randomDevice struct{}
|
||||
|
||||
// Open implements vfs.Device.Open.
|
||||
|
@ -44,6 +46,8 @@ func (randomDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry,
|
|||
}
|
||||
|
||||
// randomFD implements vfs.FileDescriptionImpl for /dev/random.
|
||||
//
|
||||
// +stateify savable
|
||||
type randomFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -27,6 +27,8 @@ import (
|
|||
const zeroDevMinor = 5
|
||||
|
||||
// zeroDevice implements vfs.Device for /dev/zero.
|
||||
//
|
||||
// +stateify savable
|
||||
type zeroDevice struct{}
|
||||
|
||||
// Open implements vfs.Device.Open.
|
||||
|
@ -41,6 +43,8 @@ func (zeroDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, op
|
|||
}
|
||||
|
||||
// zeroFD implements vfs.FileDescriptionImpl for /dev/zero.
|
||||
//
|
||||
// +stateify savable
|
||||
type zeroFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -30,6 +30,8 @@ const (
|
|||
)
|
||||
|
||||
// ttyDevice implements vfs.Device for /dev/tty.
|
||||
//
|
||||
// +stateify savable
|
||||
type ttyDevice struct{}
|
||||
|
||||
// Open implements vfs.Device.Open.
|
||||
|
|
|
@ -35,6 +35,8 @@ import (
|
|||
const Name = "devpts"
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// Name implements vfs.FilesystemType.Name.
|
||||
|
@ -58,6 +60,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
|
|||
return fs.Filesystem.VFSFilesystem(), root.VFSDentry(), nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
|
||||
|
@ -110,6 +113,8 @@ func (fs *filesystem) Release(ctx context.Context) {
|
|||
}
|
||||
|
||||
// rootInode is the root directory inode for the devpts mounts.
|
||||
//
|
||||
// +stateify savable
|
||||
type rootInode struct {
|
||||
implStatFS
|
||||
kernfs.AlwaysValid
|
||||
|
@ -131,7 +136,7 @@ type rootInode struct {
|
|||
root *rootInode
|
||||
|
||||
// mu protects the fields below.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// replicas maps pty ids to replica inodes.
|
||||
replicas map[uint32]*replicaInode
|
||||
|
@ -242,6 +247,7 @@ func (i *rootInode) DecRef(context.Context) {
|
|||
i.rootInodeRefs.DecRef(i.Destroy)
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type implStatFS struct{}
|
||||
|
||||
// StatFS implements kernfs.Inode.StatFS.
|
||||
|
|
|
@ -31,6 +31,8 @@ import (
|
|||
)
|
||||
|
||||
// masterInode is the inode for the master end of the Terminal.
|
||||
//
|
||||
// +stateify savable
|
||||
type masterInode struct {
|
||||
implStatFS
|
||||
kernfs.InodeAttrs
|
||||
|
@ -89,6 +91,7 @@ func (mi *masterInode) SetStat(ctx context.Context, vfsfs *vfs.Filesystem, creds
|
|||
return mi.InodeAttrs.SetStat(ctx, vfsfs, creds, opts)
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type masterFileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -30,6 +30,8 @@ import (
|
|||
)
|
||||
|
||||
// replicaInode is the inode for the replica end of the Terminal.
|
||||
//
|
||||
// +stateify savable
|
||||
type replicaInode struct {
|
||||
implStatFS
|
||||
kernfs.InodeAttrs
|
||||
|
@ -95,6 +97,7 @@ func (si *replicaInode) SetStat(ctx context.Context, vfsfs *vfs.Filesystem, cred
|
|||
return si.InodeAttrs.SetStat(ctx, vfsfs, creds, opts)
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type replicaFileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -33,8 +33,10 @@ import (
|
|||
const Name = "devtmpfs"
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct {
|
||||
initOnce sync.Once
|
||||
initOnce sync.Once `state:"nosave"` // FIXME(gvisor.dev/issue/1664): not yet supported.
|
||||
initErr error
|
||||
|
||||
// fs is the tmpfs filesystem that backs all mounts of this FilesystemType.
|
||||
|
|
|
@ -33,6 +33,8 @@ import (
|
|||
// EventFileDescription implements vfs.FileDescriptionImpl for file-based event
|
||||
// notification (eventfd). Eventfds are usually internal to the Sentry but in
|
||||
// certain situations they may be converted into a host-backed eventfd.
|
||||
//
|
||||
// +stateify savable
|
||||
type EventFileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -20,6 +20,8 @@ import (
|
|||
)
|
||||
|
||||
// dentry implements vfs.DentryImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type dentry struct {
|
||||
vfsd vfs.Dentry
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ import (
|
|||
)
|
||||
|
||||
// directory represents a directory inode. It holds the childList in memory.
|
||||
//
|
||||
// +stateify savable
|
||||
type directory struct {
|
||||
inode inode
|
||||
|
||||
|
@ -39,7 +41,7 @@ type directory struct {
|
|||
// Lock Order (outermost locks must be taken first):
|
||||
// directory.mu
|
||||
// filesystem.mu
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// childList is a list containing (1) child dirents and (2) fake dirents
|
||||
// (with diskDirent == nil) that represent the iteration position of
|
||||
|
@ -120,6 +122,8 @@ func (i *inode) isDir() bool {
|
|||
}
|
||||
|
||||
// dirent is the directory.childList node.
|
||||
//
|
||||
// +stateify savable
|
||||
type dirent struct {
|
||||
diskDirent disklayout.Dirent
|
||||
|
||||
|
@ -129,6 +133,8 @@ type dirent struct {
|
|||
|
||||
// directoryFD represents a directory file description. It implements
|
||||
// vfs.FileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type directoryFD struct {
|
||||
fileDescription
|
||||
vfs.DirectoryFileDescriptionDefaultImpl
|
||||
|
|
|
@ -34,6 +34,8 @@ import (
|
|||
const Name = "ext"
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// Compiles only if FilesystemType implements vfs.FilesystemType.
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
)
|
||||
|
||||
// extentFile is a type of regular file which uses extents to store file data.
|
||||
//
|
||||
// +stateify savable
|
||||
type extentFile struct {
|
||||
regFile regularFile
|
||||
|
||||
|
|
|
@ -38,11 +38,13 @@ var (
|
|||
)
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
// mu serializes changes to the Dentry tree.
|
||||
mu sync.RWMutex
|
||||
mu sync.RWMutex `state:"nosave"`
|
||||
|
||||
// dev represents the underlying fs device. It does not require protection
|
||||
// because io.ReaderAt permits concurrent read calls to it. It translates to
|
||||
|
|
|
@ -37,6 +37,8 @@ import (
|
|||
// |-- regular--
|
||||
// |-- extent file
|
||||
// |-- block map file
|
||||
//
|
||||
// +stateify savable
|
||||
type inode struct {
|
||||
// refs is a reference count. refs is accessed using atomic memory operations.
|
||||
refs int64
|
||||
|
|
|
@ -31,6 +31,8 @@ import (
|
|||
// regularFile represents a regular file's inode. This too follows the
|
||||
// inheritance pattern prevelant in the vfs layer described in
|
||||
// pkg/sentry/vfs/README.md.
|
||||
//
|
||||
// +stateify savable
|
||||
type regularFile struct {
|
||||
inode inode
|
||||
|
||||
|
@ -67,6 +69,8 @@ func (in *inode) isRegular() bool {
|
|||
|
||||
// directoryFD represents a directory file description. It implements
|
||||
// vfs.FileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type regularFileFD struct {
|
||||
fileDescription
|
||||
vfs.LockFD
|
||||
|
@ -75,7 +79,7 @@ type regularFileFD struct {
|
|||
off int64
|
||||
|
||||
// offMu serializes operations that may mutate off.
|
||||
offMu sync.Mutex
|
||||
offMu sync.Mutex `state:"nosave"`
|
||||
}
|
||||
|
||||
// Release implements vfs.FileDescriptionImpl.Release.
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
)
|
||||
|
||||
// symlink represents a symlink inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type symlink struct {
|
||||
inode inode
|
||||
target string // immutable
|
||||
|
@ -64,6 +66,8 @@ func (in *inode) isSymlink() bool {
|
|||
// symlinkFD represents a symlink file description and implements
|
||||
// vfs.FileDescriptionImpl. which may only be used if open options contains
|
||||
// O_PATH. For this reason most of the functions return EBADF.
|
||||
//
|
||||
// +stateify savable
|
||||
type symlinkFD struct {
|
||||
fileDescription
|
||||
vfs.NoLockFD
|
||||
|
|
|
@ -39,15 +39,18 @@ const (
|
|||
)
|
||||
|
||||
// connection is the struct by which the sentry communicates with the FUSE server daemon.
|
||||
//
|
||||
// Lock order:
|
||||
// - conn.fd.mu
|
||||
// - conn.mu
|
||||
// - conn.asyncMu
|
||||
//
|
||||
// +stateify savable
|
||||
type connection struct {
|
||||
fd *DeviceFD
|
||||
|
||||
// mu protects access to struct memebers.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// attributeVersion is the version of connection's attributes.
|
||||
attributeVersion uint64
|
||||
|
@ -75,7 +78,7 @@ type connection struct {
|
|||
initialized int32
|
||||
|
||||
// initializedChan is used to block requests before initialization.
|
||||
initializedChan chan struct{}
|
||||
initializedChan chan struct{} `state:".(bool)"`
|
||||
|
||||
// connected (connection established) when a new FUSE file system is created.
|
||||
// Set to false when:
|
||||
|
@ -113,7 +116,7 @@ type connection struct {
|
|||
// i.e. `!request.noReply`
|
||||
|
||||
// asyncMu protects the async request fields.
|
||||
asyncMu sync.Mutex
|
||||
asyncMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// asyncNum is the number of async requests.
|
||||
// Protected by asyncMu.
|
||||
|
@ -174,6 +177,22 @@ type connection struct {
|
|||
noOpen bool
|
||||
}
|
||||
|
||||
func (conn *connection) saveInitializedChan() bool {
|
||||
select {
|
||||
case <-conn.initializedChan:
|
||||
return true // Closed.
|
||||
default:
|
||||
return false // Not closed.
|
||||
}
|
||||
}
|
||||
|
||||
func (conn *connection) loadInitializedChan(closed bool) {
|
||||
conn.initializedChan = make(chan struct{}, 1)
|
||||
if closed {
|
||||
close(conn.initializedChan)
|
||||
}
|
||||
}
|
||||
|
||||
// newFUSEConnection creates a FUSE connection to fd.
|
||||
func newFUSEConnection(_ context.Context, fd *vfs.FileDescription, opts *filesystemOptions) (*connection, error) {
|
||||
// Mark the device as ready so it can be used. /dev/fuse can only be used if the FD was used to
|
||||
|
|
|
@ -31,6 +31,8 @@ import (
|
|||
const fuseDevMinor = 229
|
||||
|
||||
// fuseDevice implements vfs.Device for /dev/fuse.
|
||||
//
|
||||
// +stateify savable
|
||||
type fuseDevice struct{}
|
||||
|
||||
// Open implements vfs.Device.Open.
|
||||
|
@ -49,6 +51,8 @@ func (fuseDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, op
|
|||
}
|
||||
|
||||
// DeviceFD implements vfs.FileDescriptionImpl for /dev/fuse.
|
||||
//
|
||||
// +stateify savable
|
||||
type DeviceFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
@ -79,7 +83,7 @@ type DeviceFD struct {
|
|||
writeCursorFR *futureResponse
|
||||
|
||||
// mu protects all the queues, maps, buffers and cursors and nextOpID.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// waitQueue is used to notify interested parties when the device becomes
|
||||
// readable or writable.
|
||||
|
@ -88,12 +92,20 @@ type DeviceFD struct {
|
|||
// fullQueueCh is a channel used to synchronize the readers with the writers.
|
||||
// Writers (inbound requests to the filesystem) block if there are too many
|
||||
// unprocessed in-flight requests.
|
||||
fullQueueCh chan struct{}
|
||||
fullQueueCh chan struct{} `state:".(int)"`
|
||||
|
||||
// fs is the FUSE filesystem that this FD is being used for.
|
||||
fs *filesystem
|
||||
}
|
||||
|
||||
func (fd *DeviceFD) saveFullQueueCh() int {
|
||||
return cap(fd.fullQueueCh)
|
||||
}
|
||||
|
||||
func (fd *DeviceFD) loadFullQueueCh(capacity int) {
|
||||
fd.fullQueueCh = make(chan struct{}, capacity)
|
||||
}
|
||||
|
||||
// Release implements vfs.FileDescriptionImpl.Release.
|
||||
func (fd *DeviceFD) Release(ctx context.Context) {
|
||||
if fd.fs != nil {
|
||||
|
|
|
@ -41,8 +41,11 @@ const Name = "fuse"
|
|||
const maxActiveRequestsDefault = 10000
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// +stateify savable
|
||||
type filesystemOptions struct {
|
||||
// userID specifies the numeric uid of the mount owner.
|
||||
// This option should not be specified by the filesystem owner.
|
||||
|
@ -73,6 +76,8 @@ type filesystemOptions struct {
|
|||
}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
devMinor uint32
|
||||
|
@ -240,6 +245,8 @@ func (fs *filesystem) Release(ctx context.Context) {
|
|||
}
|
||||
|
||||
// inode implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type inode struct {
|
||||
inodeRefs
|
||||
kernfs.InodeAttrs
|
||||
|
|
|
@ -117,11 +117,12 @@ func (d *dentry) createSyntheticChildLocked(opts *createSyntheticOpts) {
|
|||
d.syntheticChildren++
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type directoryFD struct {
|
||||
fileDescription
|
||||
vfs.DirectoryFileDescriptionDefaultImpl
|
||||
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
off int64
|
||||
dirents []vfs.Dirent
|
||||
}
|
||||
|
|
|
@ -62,9 +62,13 @@ import (
|
|||
const Name = "9p"
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
|
@ -77,7 +81,7 @@ type filesystem struct {
|
|||
iopts InternalFilesystemOptions
|
||||
|
||||
// client is the client used by this filesystem. client is immutable.
|
||||
client *p9.Client
|
||||
client *p9.Client `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
|
||||
// clock is a realtime clock used to set timestamps in file operations.
|
||||
clock ktime.Clock
|
||||
|
@ -95,7 +99,7 @@ type filesystem struct {
|
|||
// reference count (such that it is usable as vfs.ResolvingPath.Start() or
|
||||
// is reachable from its children), or if it is a child dentry (such that
|
||||
// it is reachable from its parent).
|
||||
renameMu sync.RWMutex
|
||||
renameMu sync.RWMutex `state:"nosave"`
|
||||
|
||||
// cachedDentries contains all dentries with 0 references. (Due to race
|
||||
// conditions, it may also contain dentries with non-zero references.)
|
||||
|
@ -107,7 +111,7 @@ type filesystem struct {
|
|||
// syncableDentries contains all dentries in this filesystem for which
|
||||
// !dentry.file.isNil(). specialFileFDs contains all open specialFileFDs.
|
||||
// These fields are protected by syncMu.
|
||||
syncMu sync.Mutex
|
||||
syncMu sync.Mutex `state:"nosave"`
|
||||
syncableDentries map[*dentry]struct{}
|
||||
specialFileFDs map[*specialFileFD]struct{}
|
||||
|
||||
|
@ -120,6 +124,8 @@ type filesystem struct {
|
|||
// dentries, it comes from QID.Path from the 9P server. Synthetic dentries
|
||||
// have have their inodeNumber generated sequentially, with the MSB reserved to
|
||||
// prevent conflicts with regular dentries.
|
||||
//
|
||||
// +stateify savable
|
||||
type inodeNumber uint64
|
||||
|
||||
// Reserve MSB for synthetic mounts.
|
||||
|
@ -132,6 +138,7 @@ func inoFromPath(path uint64) inodeNumber {
|
|||
return inodeNumber(path &^ syntheticInoMask)
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type filesystemOptions struct {
|
||||
// "Standard" 9P options.
|
||||
fd int
|
||||
|
@ -177,6 +184,8 @@ type filesystemOptions struct {
|
|||
|
||||
// InteropMode controls the client's interaction with other remote filesystem
|
||||
// users.
|
||||
//
|
||||
// +stateify savable
|
||||
type InteropMode uint32
|
||||
|
||||
const (
|
||||
|
@ -235,6 +244,8 @@ const (
|
|||
|
||||
// InternalFilesystemOptions may be passed as
|
||||
// vfs.GetFilesystemOptions.InternalData to FilesystemType.GetFilesystem.
|
||||
//
|
||||
// +stateify savable
|
||||
type InternalFilesystemOptions struct {
|
||||
// If LeakConnection is true, do not close the connection to the server
|
||||
// when the Filesystem is released. This is necessary for deployments in
|
||||
|
@ -534,6 +545,8 @@ func (fs *filesystem) Release(ctx context.Context) {
|
|||
}
|
||||
|
||||
// dentry implements vfs.DentryImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type dentry struct {
|
||||
vfsd vfs.Dentry
|
||||
|
||||
|
@ -563,7 +576,7 @@ type dentry struct {
|
|||
// If file.isNil(), this dentry represents a synthetic file, i.e. a file
|
||||
// that does not exist on the remote filesystem. As of this writing, the
|
||||
// only files that can be synthetic are sockets, pipes, and directories.
|
||||
file p9file
|
||||
file p9file `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
|
||||
// If deleted is non-zero, the file represented by this dentry has been
|
||||
// deleted. deleted is accessed using atomic memory operations.
|
||||
|
@ -575,7 +588,7 @@ type dentry struct {
|
|||
cached bool
|
||||
dentryEntry
|
||||
|
||||
dirMu sync.Mutex
|
||||
dirMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// If this dentry represents a directory, children contains:
|
||||
//
|
||||
|
@ -607,7 +620,7 @@ type dentry struct {
|
|||
// To mutate:
|
||||
// - Lock metadataMu and use atomic operations to update because we might
|
||||
// have atomic readers that don't hold the lock.
|
||||
metadataMu sync.Mutex
|
||||
metadataMu sync.Mutex `state:"nosave"`
|
||||
ino inodeNumber // immutable
|
||||
mode uint32 // type is immutable, perms are mutable
|
||||
uid uint32 // auth.KUID, but stored as raw uint32 for sync/atomic
|
||||
|
@ -638,7 +651,7 @@ type dentry struct {
|
|||
// other metadata fields.
|
||||
nlink uint32
|
||||
|
||||
mapsMu sync.Mutex
|
||||
mapsMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// If this dentry represents a regular file, mappings tracks mappings of
|
||||
// the file into memmap.MappingSpaces. mappings is protected by mapsMu.
|
||||
|
@ -662,12 +675,12 @@ type dentry struct {
|
|||
// either p9.File transitions from closed (isNil() == true) to open
|
||||
// (isNil() == false), it may be mutated with handleMu locked, but cannot
|
||||
// be closed until the dentry is destroyed.
|
||||
handleMu sync.RWMutex
|
||||
readFile p9file
|
||||
writeFile p9file
|
||||
handleMu sync.RWMutex `state:"nosave"`
|
||||
readFile p9file `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
writeFile p9file `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
hostFD int32
|
||||
|
||||
dataMu sync.RWMutex
|
||||
dataMu sync.RWMutex `state:"nosave"`
|
||||
|
||||
// If this dentry represents a regular file that is client-cached, cache
|
||||
// maps offsets into the cached file to offsets into
|
||||
|
@ -1627,12 +1640,14 @@ func (d *dentry) decLinks() {
|
|||
|
||||
// fileDescription is embedded by gofer implementations of
|
||||
// vfs.FileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type fileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
vfs.LockFD
|
||||
|
||||
lockLogging sync.Once
|
||||
lockLogging sync.Once `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
}
|
||||
|
||||
func (fd *fileDescription) filesystem() *filesystem {
|
||||
|
|
|
@ -25,6 +25,8 @@ import (
|
|||
|
||||
// handle represents a remote "open file descriptor", consisting of an opened
|
||||
// fid (p9.File) and optionally a host file descriptor.
|
||||
//
|
||||
// These are explicitly not savable.
|
||||
type handle struct {
|
||||
file p9file
|
||||
fd int32 // -1 if unavailable
|
||||
|
|
|
@ -39,11 +39,12 @@ func (d *dentry) isRegularFile() bool {
|
|||
return d.fileType() == linux.S_IFREG
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type regularFileFD struct {
|
||||
fileDescription
|
||||
|
||||
// off is the file offset. off is protected by mu.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
off int64
|
||||
}
|
||||
|
||||
|
@ -898,6 +899,8 @@ func (d *dentry) Evict(ctx context.Context, er pgalloc.EvictableRange) {
|
|||
// dentryPlatformFile is only used when a host FD representing the remote file
|
||||
// is available (i.e. dentry.hostFD >= 0), and that FD is used for application
|
||||
// memory mappings (i.e. !filesystem.opts.forcePageCache).
|
||||
//
|
||||
// +stateify savable
|
||||
type dentryPlatformFile struct {
|
||||
*dentry
|
||||
|
||||
|
@ -910,7 +913,7 @@ type dentryPlatformFile struct {
|
|||
hostFileMapper fsutil.HostFileMapper
|
||||
|
||||
// hostFileMapperInitOnce is used to lazily initialize hostFileMapper.
|
||||
hostFileMapperInitOnce sync.Once
|
||||
hostFileMapperInitOnce sync.Once `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
}
|
||||
|
||||
// IncRef implements memmap.File.IncRef.
|
||||
|
|
|
@ -36,12 +36,14 @@ func (d *dentry) isSocket() bool {
|
|||
// An endpoint's lifetime is the time between when filesystem.BoundEndpointAt()
|
||||
// is called and either BoundEndpoint.BidirectionalConnect or
|
||||
// BoundEndpoint.UnidirectionalConnect is called.
|
||||
//
|
||||
// +stateify savable
|
||||
type endpoint struct {
|
||||
// dentry is the filesystem dentry which produced this endpoint.
|
||||
dentry *dentry
|
||||
|
||||
// file is the p9 file that contains a single unopened fid.
|
||||
file p9.File
|
||||
file p9.File `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
|
||||
// path is the sentry path where this endpoint is bound.
|
||||
path string
|
||||
|
|
|
@ -34,11 +34,13 @@ import (
|
|||
// special files, and (when filesystemOptions.regularFilesUseSpecialFileFD is
|
||||
// in effect) regular files. specialFileFD differs from regularFileFD by using
|
||||
// per-FD handles instead of shared per-dentry handles, and never buffering I/O.
|
||||
//
|
||||
// +stateify savable
|
||||
type specialFileFD struct {
|
||||
fileDescription
|
||||
|
||||
// handle is used for file I/O. handle is immutable.
|
||||
handle handle
|
||||
handle handle `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
|
||||
// isRegularFile is true if this FD represents a regular file which is only
|
||||
// possible when filesystemOptions.regularFilesUseSpecialFileFD is in
|
||||
|
@ -56,7 +58,7 @@ type specialFileFD struct {
|
|||
queue waiter.Queue
|
||||
|
||||
// If seekable is true, off is the file offset. off is protected by mu.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
off int64
|
||||
}
|
||||
|
||||
|
|
|
@ -137,6 +137,8 @@ func ImportFD(ctx context.Context, mnt *vfs.Mount, hostFD int, isTTY bool) (*vfs
|
|||
}
|
||||
|
||||
// filesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystemType struct{}
|
||||
|
||||
// GetFilesystem implements vfs.FilesystemType.GetFilesystem.
|
||||
|
@ -166,6 +168,8 @@ func NewFilesystem(vfsObj *vfs.VirtualFilesystem) (*vfs.Filesystem, error) {
|
|||
}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
|
||||
|
@ -185,6 +189,8 @@ func (fs *filesystem) PrependPath(ctx context.Context, vfsroot, vd vfs.VirtualDe
|
|||
}
|
||||
|
||||
// inode implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type inode struct {
|
||||
kernfs.InodeNoStatFS
|
||||
kernfs.InodeNotDirectory
|
||||
|
@ -233,7 +239,7 @@ type inode struct {
|
|||
canMap bool
|
||||
|
||||
// mapsMu protects mappings.
|
||||
mapsMu sync.Mutex
|
||||
mapsMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// If canMap is true, mappings tracks mappings of hostFD into
|
||||
// memmap.MappingSpaces.
|
||||
|
@ -511,6 +517,8 @@ func (i *inode) open(ctx context.Context, d *kernfs.Dentry, mnt *vfs.Mount, flag
|
|||
}
|
||||
|
||||
// fileDescription is embedded by host fd implementations of FileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type fileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
@ -525,7 +533,7 @@ type fileDescription struct {
|
|||
inode *inode
|
||||
|
||||
// offsetMu protects offset.
|
||||
offsetMu sync.Mutex
|
||||
offsetMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// offset specifies the current file offset. It is only meaningful when
|
||||
// inode.seekable is true.
|
||||
|
|
|
@ -27,11 +27,13 @@ import (
|
|||
// cannot implement both kernfs.Inode.IncRef and memmap.File.IncRef.
|
||||
//
|
||||
// inodePlatformFile should only be used if inode.canMap is true.
|
||||
//
|
||||
// +stateify savable
|
||||
type inodePlatformFile struct {
|
||||
*inode
|
||||
|
||||
// fdRefsMu protects fdRefs.
|
||||
fdRefsMu sync.Mutex
|
||||
fdRefsMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// fdRefs counts references on memmap.File offsets. It is used solely for
|
||||
// memory accounting.
|
||||
|
@ -41,7 +43,7 @@ type inodePlatformFile struct {
|
|||
fileMapper fsutil.HostFileMapper
|
||||
|
||||
// fileMapperInitOnce is used to lazily initialize fileMapper.
|
||||
fileMapperInitOnce sync.Once
|
||||
fileMapperInitOnce sync.Once `state:"nosave"` // FIXME(gvisor.dev/issue/1663): not yet supported.
|
||||
}
|
||||
|
||||
// IncRef implements memmap.File.IncRef.
|
||||
|
|
|
@ -30,6 +30,8 @@ import (
|
|||
|
||||
// TTYFileDescription implements vfs.FileDescriptionImpl for a host file
|
||||
// descriptor that wraps a TTY FD.
|
||||
//
|
||||
// +stateify savable
|
||||
type TTYFileDescription struct {
|
||||
fileDescription
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ import (
|
|||
)
|
||||
|
||||
// SeekEndConfig describes the SEEK_END behaviour for FDs.
|
||||
//
|
||||
// +stateify savable
|
||||
type SeekEndConfig int
|
||||
|
||||
// Constants related to SEEK_END behaviour for FDs.
|
||||
|
@ -41,6 +43,8 @@ const (
|
|||
)
|
||||
|
||||
// GenericDirectoryFDOptions contains configuration for a GenericDirectoryFD.
|
||||
//
|
||||
// +stateify savable
|
||||
type GenericDirectoryFDOptions struct {
|
||||
SeekEnd SeekEndConfig
|
||||
}
|
||||
|
@ -56,6 +60,8 @@ type GenericDirectoryFDOptions struct {
|
|||
// Must be initialize with Init before first use.
|
||||
//
|
||||
// Lock ordering: mu => children.mu.
|
||||
//
|
||||
// +stateify savable
|
||||
type GenericDirectoryFD struct {
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
vfs.DirectoryFileDescriptionDefaultImpl
|
||||
|
@ -68,7 +74,7 @@ type GenericDirectoryFD struct {
|
|||
children *OrderedChildren
|
||||
|
||||
// mu protects the fields below.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// off is the current directory offset. Protected by "mu".
|
||||
off int64
|
||||
|
|
|
@ -31,6 +31,8 @@ import (
|
|||
// count for inodes, performing no extra actions when references are obtained or
|
||||
// released. This is suitable for simple file inodes that don't reference any
|
||||
// resources.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeNoopRefCount struct {
|
||||
}
|
||||
|
||||
|
@ -50,6 +52,8 @@ func (InodeNoopRefCount) TryIncRef() bool {
|
|||
// InodeDirectoryNoNewChildren partially implements the Inode interface.
|
||||
// InodeDirectoryNoNewChildren represents a directory inode which does not
|
||||
// support creation of new children.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeDirectoryNoNewChildren struct{}
|
||||
|
||||
// NewFile implements Inode.NewFile.
|
||||
|
@ -81,6 +85,8 @@ func (InodeDirectoryNoNewChildren) NewNode(context.Context, string, vfs.MknodOpt
|
|||
// inodeDirectory and inodeDynamicDirectory sub interfaces. Inodes that do not
|
||||
// represent directories can embed this to provide no-op implementations for
|
||||
// directory-related functions.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeNotDirectory struct {
|
||||
}
|
||||
|
||||
|
@ -149,6 +155,8 @@ func (InodeNotDirectory) Valid(context.Context) bool {
|
|||
// dymanic entries (i.e. entries that are not "hashed" into the
|
||||
// vfs.Dentry.children) can embed this to provide no-op implementations for
|
||||
// functions related to dynamic entries.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeNoDynamicLookup struct{}
|
||||
|
||||
// Lookup implements Inode.Lookup.
|
||||
|
@ -169,6 +177,8 @@ func (InodeNoDynamicLookup) Valid(ctx context.Context) bool {
|
|||
// InodeNotSymlink partially implements the Inode interface, specifically the
|
||||
// inodeSymlink sub interface. All inodes that are not symlinks may embed this
|
||||
// to return the appropriate errors from symlink-related functions.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeNotSymlink struct{}
|
||||
|
||||
// Readlink implements Inode.Readlink.
|
||||
|
@ -186,6 +196,8 @@ func (InodeNotSymlink) Getlink(context.Context, *vfs.Mount) (vfs.VirtualDentry,
|
|||
// inode attributes.
|
||||
//
|
||||
// Must be initialized by Init prior to first use.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeAttrs struct {
|
||||
devMajor uint32
|
||||
devMinor uint32
|
||||
|
@ -330,6 +342,7 @@ func (a *InodeAttrs) DecLinks() {
|
|||
}
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type slot struct {
|
||||
Name string
|
||||
Dentry *vfs.Dentry
|
||||
|
@ -337,6 +350,8 @@ type slot struct {
|
|||
}
|
||||
|
||||
// OrderedChildrenOptions contains initialization options for OrderedChildren.
|
||||
//
|
||||
// +stateify savable
|
||||
type OrderedChildrenOptions struct {
|
||||
// Writable indicates whether vfs.FilesystemImpl methods implemented by
|
||||
// OrderedChildren may modify the tracked children. This applies to
|
||||
|
@ -352,12 +367,14 @@ type OrderedChildrenOptions struct {
|
|||
// directories.
|
||||
//
|
||||
// Must be initialize with Init before first use.
|
||||
//
|
||||
// +stateify savable
|
||||
type OrderedChildren struct {
|
||||
// Can children be modified by user syscalls? It set to false, interface
|
||||
// methods that would modify the children return EPERM. Immutable.
|
||||
writable bool
|
||||
|
||||
mu sync.RWMutex
|
||||
mu sync.RWMutex `state:"nosave"`
|
||||
order slotList
|
||||
set map[string]*slot
|
||||
}
|
||||
|
@ -484,6 +501,7 @@ func (o *OrderedChildren) RmDir(ctx context.Context, name string, child *vfs.Den
|
|||
return o.Unlink(ctx, name, child)
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type renameAcrossDifferentImplementationsError struct{}
|
||||
|
||||
func (renameAcrossDifferentImplementationsError) Error() string {
|
||||
|
@ -542,6 +560,8 @@ func (o *OrderedChildren) nthLocked(i int64) *slot {
|
|||
}
|
||||
|
||||
// InodeSymlink partially implements Inode interface for symlinks.
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeSymlink struct {
|
||||
InodeNotDirectory
|
||||
}
|
||||
|
@ -615,6 +635,8 @@ func (s *StaticDirectory) DecRef(context.Context) {
|
|||
}
|
||||
|
||||
// AlwaysValid partially implements kernfs.inodeDynamicLookup.
|
||||
//
|
||||
// +stateify savable
|
||||
type AlwaysValid struct{}
|
||||
|
||||
// Valid implements kernfs.inodeDynamicLookup.Valid.
|
||||
|
@ -624,6 +646,8 @@ func (*AlwaysValid) Valid(context.Context) bool {
|
|||
|
||||
// InodeNoStatFS partially implements the Inode interface, where the client
|
||||
// filesystem doesn't support statfs(2).
|
||||
//
|
||||
// +stateify savable
|
||||
type InodeNoStatFS struct{}
|
||||
|
||||
// StatFS implements Inode.StatFS.
|
||||
|
|
|
@ -66,10 +66,12 @@ import (
|
|||
// Filesystem mostly implements vfs.FilesystemImpl for a generic in-memory
|
||||
// filesystem. Concrete implementations are expected to embed this in their own
|
||||
// Filesystem type.
|
||||
//
|
||||
// +stateify savable
|
||||
type Filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
droppedDentriesMu sync.Mutex
|
||||
droppedDentriesMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// droppedDentries is a list of dentries waiting to be DecRef()ed. This is
|
||||
// used to defer dentry destruction until mu can be acquired for
|
||||
|
@ -97,7 +99,7 @@ type Filesystem struct {
|
|||
// defer fs.mu.RUnlock()
|
||||
// ...
|
||||
// fs.deferDecRef(dentry)
|
||||
mu sync.RWMutex
|
||||
mu sync.RWMutex `state:"nosave"`
|
||||
|
||||
// nextInoMinusOne is used to to allocate inode numbers on this
|
||||
// filesystem. Must be accessed by atomic operations.
|
||||
|
@ -160,6 +162,8 @@ const (
|
|||
// to, and child dentries hold a reference on their parent.
|
||||
//
|
||||
// Must be initialized by Init prior to first use.
|
||||
//
|
||||
// +stateify savable
|
||||
type Dentry struct {
|
||||
DentryRefs
|
||||
|
||||
|
@ -173,7 +177,7 @@ type Dentry struct {
|
|||
name string
|
||||
|
||||
// dirMu protects children and the names of child Dentries.
|
||||
dirMu sync.Mutex
|
||||
dirMu sync.Mutex `state:"nosave"`
|
||||
children map[string]*Dentry
|
||||
|
||||
inode Inode
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
|
||||
// StaticSymlink provides an Inode implementation for symlinks that point to
|
||||
// a immutable target.
|
||||
//
|
||||
// +stateify savable
|
||||
type StaticSymlink struct {
|
||||
InodeAttrs
|
||||
InodeNoopRefCount
|
||||
|
|
|
@ -100,12 +100,13 @@ func (d *dentry) collectWhiteoutsForRmdirLocked(ctx context.Context) (map[string
|
|||
return whiteouts, readdirErr
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type directoryFD struct {
|
||||
fileDescription
|
||||
vfs.DirectoryFileDescriptionDefaultImpl
|
||||
vfs.DentryMetadataFileDescriptionImpl
|
||||
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
off int64
|
||||
dirents []vfs.Dirent
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ func (d *dentry) readlink(ctx context.Context) (string, error) {
|
|||
})
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type nonDirectoryFD struct {
|
||||
fileDescription
|
||||
|
||||
|
@ -47,7 +48,7 @@ type nonDirectoryFD struct {
|
|||
// fileDescription.dentry().upperVD. cachedFlags is the last known value of
|
||||
// cachedFD.StatusFlags(). copiedUp, cachedFD, and cachedFlags are
|
||||
// protected by mu.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
copiedUp bool
|
||||
cachedFD *vfs.FileDescription
|
||||
cachedFlags uint32
|
||||
|
|
|
@ -51,6 +51,8 @@ import (
|
|||
const Name = "overlay"
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// Name implements vfs.FilesystemType.Name.
|
||||
|
@ -60,6 +62,8 @@ func (FilesystemType) Name() string {
|
|||
|
||||
// FilesystemOptions may be passed as vfs.GetFilesystemOptions.InternalData to
|
||||
// FilesystemType.GetFilesystem.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemOptions struct {
|
||||
// Callers passing FilesystemOptions to
|
||||
// overlay.FilesystemType.GetFilesystem() are responsible for ensuring that
|
||||
|
@ -76,6 +80,8 @@ type FilesystemOptions struct {
|
|||
}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
|
@ -98,7 +104,7 @@ type filesystem struct {
|
|||
// renameMu synchronizes renaming with non-renaming operations in order to
|
||||
// ensure consistent lock ordering between dentry.dirMu in different
|
||||
// dentries.
|
||||
renameMu sync.RWMutex
|
||||
renameMu sync.RWMutex `state:"nosave"`
|
||||
|
||||
// lastDirIno is the last inode number assigned to a directory. lastDirIno
|
||||
// is accessed using atomic memory operations.
|
||||
|
@ -367,6 +373,8 @@ func (fs *filesystem) newDirIno() uint64 {
|
|||
}
|
||||
|
||||
// dentry implements vfs.DentryImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type dentry struct {
|
||||
vfsd vfs.Dentry
|
||||
|
||||
|
@ -399,7 +407,7 @@ type dentry struct {
|
|||
// and dirents (if not nil) is a cache of dirents as returned by
|
||||
// directoryFDs representing this directory. children is protected by
|
||||
// dirMu.
|
||||
dirMu sync.Mutex
|
||||
dirMu sync.Mutex `state:"nosave"`
|
||||
children map[string]*dentry
|
||||
dirents []vfs.Dirent
|
||||
|
||||
|
@ -409,7 +417,7 @@ type dentry struct {
|
|||
// If !upperVD.Ok(), it can transition to a valid vfs.VirtualDentry (i.e.
|
||||
// be copied up) with copyMu locked for writing; otherwise, it is
|
||||
// immutable. lowerVDs is always immutable.
|
||||
copyMu sync.RWMutex
|
||||
copyMu sync.RWMutex `state:"nosave"`
|
||||
upperVD vfs.VirtualDentry
|
||||
lowerVDs []vfs.VirtualDentry
|
||||
|
||||
|
@ -652,6 +660,8 @@ func (d *dentry) updateAfterSetStatLocked(opts *vfs.SetStatOptions) {
|
|||
|
||||
// fileDescription is embedded by overlay implementations of
|
||||
// vfs.FileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type fileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type filesystemType struct{}
|
||||
|
||||
// Name implements vfs.FilesystemType.Name.
|
||||
|
@ -43,6 +44,7 @@ func (filesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFile
|
|||
panic("pipefs.filesystemType.GetFilesystem should never be called")
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
|
||||
|
@ -76,6 +78,8 @@ func (fs *filesystem) PrependPath(ctx context.Context, vfsroot, vd vfs.VirtualDe
|
|||
}
|
||||
|
||||
// inode implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type inode struct {
|
||||
kernfs.InodeNotDirectory
|
||||
kernfs.InodeNotSymlink
|
||||
|
|
|
@ -41,6 +41,7 @@ func (FilesystemType) Name() string {
|
|||
return Name
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
|
||||
|
@ -84,6 +85,8 @@ func (fs *filesystem) Release(ctx context.Context) {
|
|||
|
||||
// dynamicInode is an overfitted interface for common Inodes with
|
||||
// dynamicByteSource types used in procfs.
|
||||
//
|
||||
// +stateify savable
|
||||
type dynamicInode interface {
|
||||
kernfs.Inode
|
||||
vfs.DynamicBytesSource
|
||||
|
@ -99,6 +102,7 @@ func (fs *filesystem) newDentry(creds *auth.Credentials, ino uint64, perm linux.
|
|||
return d
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type staticFile struct {
|
||||
kernfs.DynamicBytesFile
|
||||
vfs.StaticData
|
||||
|
@ -118,10 +122,13 @@ func newStaticDir(creds *auth.Credentials, devMajor, devMinor uint32, ino uint64
|
|||
|
||||
// InternalData contains internal data passed in to the procfs mount via
|
||||
// vfs.GetFilesystemOptions.InternalData.
|
||||
//
|
||||
// +stateify savable
|
||||
type InternalData struct {
|
||||
Cgroups map[string]string
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type implStatFS struct{}
|
||||
|
||||
// StatFS implements kernfs.Inode.StatFS.
|
||||
|
|
|
@ -116,6 +116,7 @@ func (i *subtasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallb
|
|||
return offset, nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type subtasksFD struct {
|
||||
kernfs.GenericDirectoryFD
|
||||
|
||||
|
|
|
@ -129,6 +129,8 @@ func (i *taskInode) DecRef(context.Context) {
|
|||
|
||||
// taskOwnedInode implements kernfs.Inode and overrides inode owner with task
|
||||
// effective user and group.
|
||||
//
|
||||
// +stateify savable
|
||||
type taskOwnedInode struct {
|
||||
kernfs.Inode
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ func taskFDExists(ctx context.Context, t *kernel.Task, fd int32) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type fdDir struct {
|
||||
locks vfs.FileLocks
|
||||
|
||||
|
|
|
@ -785,6 +785,7 @@ func (i *mountsData) Generate(ctx context.Context, buf *bytes.Buffer) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type namespaceSymlink struct {
|
||||
kernfs.StaticSymlink
|
||||
|
||||
|
@ -832,6 +833,8 @@ func (s *namespaceSymlink) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.Vir
|
|||
|
||||
// namespaceInode is a synthetic inode created to represent a namespace in
|
||||
// /proc/[pid]/ns/*.
|
||||
//
|
||||
// +stateify savable
|
||||
type namespaceInode struct {
|
||||
implStatFS
|
||||
kernfs.InodeAttrs
|
||||
|
@ -865,6 +868,8 @@ func (i *namespaceInode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *ker
|
|||
|
||||
// namespace FD is a synthetic file that represents a namespace in
|
||||
// /proc/[pid]/ns/*.
|
||||
//
|
||||
// +stateify savable
|
||||
type namespaceFD struct {
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
vfs.LockFD
|
||||
|
|
|
@ -616,6 +616,7 @@ type netSnmpData struct {
|
|||
|
||||
var _ dynamicInode = (*netSnmpData)(nil)
|
||||
|
||||
// +stateify savable
|
||||
type snmpLine struct {
|
||||
prefix string
|
||||
header string
|
||||
|
|
|
@ -236,6 +236,8 @@ func (i *tasksInode) DecRef(context.Context) {
|
|||
// staticFileSetStat implements a special static file that allows inode
|
||||
// attributes to be set. This is to support /proc files that are readonly, but
|
||||
// allow attributes to be set.
|
||||
//
|
||||
// +stateify savable
|
||||
type staticFileSetStat struct {
|
||||
dynamicBytesFileSetAttr
|
||||
vfs.StaticData
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type selfSymlink struct {
|
||||
implStatFS
|
||||
kernfs.InodeAttrs
|
||||
|
@ -74,6 +75,7 @@ func (*selfSymlink) SetStat(context.Context, *vfs.Filesystem, *auth.Credentials,
|
|||
return syserror.EPERM
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type threadSelfSymlink struct {
|
||||
implStatFS
|
||||
kernfs.InodeAttrs
|
||||
|
@ -121,6 +123,8 @@ func (*threadSelfSymlink) SetStat(context.Context, *vfs.Filesystem, *auth.Creden
|
|||
// dynamicBytesFileSetAttr implements a special file that allows inode
|
||||
// attributes to be set. This is to support /proc files that are readonly, but
|
||||
// allow attributes to be set.
|
||||
//
|
||||
// +stateify savable
|
||||
type dynamicBytesFileSetAttr struct {
|
||||
kernfs.DynamicBytesFile
|
||||
}
|
||||
|
@ -131,6 +135,8 @@ func (d *dynamicBytesFileSetAttr) SetStat(ctx context.Context, fs *vfs.Filesyste
|
|||
}
|
||||
|
||||
// cpuStats contains the breakdown of CPU time for /proc/stat.
|
||||
//
|
||||
// +stateify savable
|
||||
type cpuStats struct {
|
||||
// user is time spent in userspace tasks with non-positive niceness.
|
||||
user uint64
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type tcpMemDir int
|
||||
|
||||
const (
|
||||
|
|
|
@ -27,6 +27,8 @@ import (
|
|||
)
|
||||
|
||||
// SignalFileDescription implements vfs.FileDescriptionImpl for signal fds.
|
||||
//
|
||||
// +stateify savable
|
||||
type SignalFileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
@ -43,7 +45,7 @@ type SignalFileDescription struct {
|
|||
target *kernel.Task
|
||||
|
||||
// mu protects mask.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// mask is the signal mask. Protected by mu.
|
||||
mask linux.SignalSet
|
||||
|
|
|
@ -28,6 +28,8 @@ import (
|
|||
)
|
||||
|
||||
// filesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystemType struct{}
|
||||
|
||||
// GetFilesystem implements vfs.FilesystemType.GetFilesystem.
|
||||
|
@ -44,6 +46,7 @@ func (filesystemType) Name() string {
|
|||
return "sockfs"
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
|
||||
|
@ -80,6 +83,8 @@ func (fs *filesystem) PrependPath(ctx context.Context, vfsroot, vd vfs.VirtualDe
|
|||
}
|
||||
|
||||
// inode implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type inode struct {
|
||||
kernfs.InodeAttrs
|
||||
kernfs.InodeNoopRefCount
|
||||
|
|
|
@ -36,6 +36,8 @@ func (fs *filesystem) newKcovFile(ctx context.Context, creds *auth.Credentials)
|
|||
}
|
||||
|
||||
// kcovInode implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type kcovInode struct {
|
||||
kernfs.InodeAttrs
|
||||
kernfs.InodeNoopRefCount
|
||||
|
@ -63,6 +65,7 @@ func (i *kcovInode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.D
|
|||
return &fd.vfsfd, nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type kcovFD struct {
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
vfs.NoLockFD
|
||||
|
|
|
@ -34,9 +34,13 @@ const Name = "sysfs"
|
|||
const defaultSysDirMode = linux.FileMode(0755)
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
kernfs.Filesystem
|
||||
|
||||
|
@ -117,6 +121,8 @@ func (fs *filesystem) Release(ctx context.Context) {
|
|||
}
|
||||
|
||||
// dir implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type dir struct {
|
||||
dirRefs
|
||||
kernfs.InodeAttrs
|
||||
|
@ -169,6 +175,8 @@ func (d *dir) StatFS(ctx context.Context, fs *vfs.Filesystem) (linux.Statfs, err
|
|||
}
|
||||
|
||||
// cpuFile implements kernfs.Inode.
|
||||
//
|
||||
// +stateify savable
|
||||
type cpuFile struct {
|
||||
implStatFS
|
||||
kernfs.DynamicBytesFile
|
||||
|
@ -190,6 +198,7 @@ func (fs *filesystem) newCPUFile(creds *auth.Credentials, maxCores uint, mode li
|
|||
return d
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type implStatFS struct{}
|
||||
|
||||
// StatFS implements kernfs.Inode.StatFS.
|
||||
|
|
|
@ -28,6 +28,8 @@ import (
|
|||
|
||||
// TimerFileDescription implements vfs.FileDescriptionImpl for timer fds. It also
|
||||
// implements ktime.TimerListener.
|
||||
//
|
||||
// +stateify savable
|
||||
type TimerFileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type deviceFile struct {
|
||||
inode inode
|
||||
kind vfs.DeviceKind
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type directory struct {
|
||||
// Since directories can't be hard-linked, each directory can only be
|
||||
// associated with a single dentry, which we can store in the directory
|
||||
|
@ -44,7 +45,7 @@ type directory struct {
|
|||
// (with inode == nil) that represent the iteration position of
|
||||
// directoryFDs. childList is used to support directoryFD.IterDirents()
|
||||
// efficiently. childList is protected by iterMu.
|
||||
iterMu sync.Mutex
|
||||
iterMu sync.Mutex `state:"nosave"`
|
||||
childList dentryList
|
||||
}
|
||||
|
||||
|
@ -86,6 +87,7 @@ func (dir *directory) mayDelete(creds *auth.Credentials, child *dentry) error {
|
|||
return vfs.CheckDeleteSticky(creds, linux.FileMode(atomic.LoadUint32(&dir.inode.mode)), auth.KUID(atomic.LoadUint32(&child.inode.uid)))
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type directoryFD struct {
|
||||
fileDescription
|
||||
vfs.DirectoryFileDescriptionDefaultImpl
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type namedPipe struct {
|
||||
inode inode
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ import (
|
|||
)
|
||||
|
||||
// regularFile is a regular (=S_IFREG) tmpfs file.
|
||||
//
|
||||
// +stateify savable
|
||||
type regularFile struct {
|
||||
inode inode
|
||||
|
||||
|
@ -66,7 +68,7 @@ type regularFile struct {
|
|||
writableMappingPages uint64
|
||||
|
||||
// dataMu protects the fields below.
|
||||
dataMu sync.RWMutex
|
||||
dataMu sync.RWMutex `state:"nosave"`
|
||||
|
||||
// data maps offsets into the file to offsets into memFile that store
|
||||
// the file's data.
|
||||
|
@ -325,13 +327,14 @@ func (*regularFile) InvalidateUnsavable(context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type regularFileFD struct {
|
||||
fileDescription
|
||||
|
||||
// off is the file offset. off is accessed using atomic memory operations.
|
||||
// offMu serializes operations that may mutate off.
|
||||
off int64
|
||||
offMu sync.Mutex
|
||||
offMu sync.Mutex `state:"nosave"`
|
||||
}
|
||||
|
||||
// Release implements vfs.FileDescriptionImpl.Release.
|
||||
|
|
|
@ -21,6 +21,8 @@ import (
|
|||
)
|
||||
|
||||
// socketFile is a socket (=S_IFSOCK) tmpfs file.
|
||||
//
|
||||
// +stateify savable
|
||||
type socketFile struct {
|
||||
inode inode
|
||||
ep transport.BoundEndpoint
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
)
|
||||
|
||||
// +stateify savable
|
||||
type symlink struct {
|
||||
inode inode
|
||||
target string // immutable
|
||||
|
|
|
@ -51,9 +51,13 @@ import (
|
|||
const Name = "tmpfs"
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
|
@ -67,7 +71,7 @@ type filesystem struct {
|
|||
devMinor uint32
|
||||
|
||||
// mu serializes changes to the Dentry tree.
|
||||
mu sync.RWMutex
|
||||
mu sync.RWMutex `state:"nosave"`
|
||||
|
||||
nextInoMinusOne uint64 // accessed using atomic memory operations
|
||||
}
|
||||
|
@ -78,6 +82,8 @@ func (FilesystemType) Name() string {
|
|||
}
|
||||
|
||||
// FilesystemOpts is used to pass configuration data to tmpfs.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemOpts struct {
|
||||
// RootFileType is the FileType of the filesystem root. Valid values
|
||||
// are: S_IFDIR, S_IFREG, and S_IFLNK. Defaults to S_IFDIR.
|
||||
|
@ -221,6 +227,8 @@ var globalStatfs = linux.Statfs{
|
|||
}
|
||||
|
||||
// dentry implements vfs.DentryImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type dentry struct {
|
||||
vfsd vfs.Dentry
|
||||
|
||||
|
@ -300,6 +308,8 @@ func (d *dentry) Watches() *vfs.Watches {
|
|||
func (d *dentry) OnZeroWatches(context.Context) {}
|
||||
|
||||
// inode represents a filesystem object.
|
||||
//
|
||||
// +stateify savable
|
||||
type inode struct {
|
||||
// fs is the owning filesystem. fs is immutable.
|
||||
fs *filesystem
|
||||
|
@ -316,12 +326,12 @@ type inode struct {
|
|||
|
||||
// Inode metadata. Writing multiple fields atomically requires holding
|
||||
// mu, othewise atomic operations can be used.
|
||||
mu sync.Mutex
|
||||
mode uint32 // file type and mode
|
||||
nlink uint32 // protected by filesystem.mu instead of inode.mu
|
||||
uid uint32 // auth.KUID, but stored as raw uint32 for sync/atomic
|
||||
gid uint32 // auth.KGID, but ...
|
||||
ino uint64 // immutable
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
mode uint32 // file type and mode
|
||||
nlink uint32 // protected by filesystem.mu instead of inode.mu
|
||||
uid uint32 // auth.KUID, but stored as raw uint32 for sync/atomic
|
||||
gid uint32 // auth.KGID, but ...
|
||||
ino uint64 // immutable
|
||||
|
||||
// Linux's tmpfs has no concept of btime.
|
||||
atime int64 // nanoseconds
|
||||
|
@ -668,6 +678,8 @@ func (i *inode) checkXattrPermissions(creds *auth.Credentials, name string, ats
|
|||
|
||||
// fileDescription is embedded by tmpfs implementations of
|
||||
// vfs.FileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type fileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -74,9 +74,13 @@ var noCrashOnVerificationFailure bool
|
|||
var verityMu sync.RWMutex
|
||||
|
||||
// FilesystemType implements vfs.FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type FilesystemType struct{}
|
||||
|
||||
// filesystem implements vfs.FilesystemImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type filesystem struct {
|
||||
vfsfs vfs.Filesystem
|
||||
|
||||
|
@ -101,11 +105,13 @@ type filesystem struct {
|
|||
// renameMu synchronizes renaming with non-renaming operations in order
|
||||
// to ensure consistent lock ordering between dentry.dirMu in different
|
||||
// dentries.
|
||||
renameMu sync.RWMutex
|
||||
renameMu sync.RWMutex `state:"nosave"`
|
||||
}
|
||||
|
||||
// InternalFilesystemOptions may be passed as
|
||||
// vfs.GetFilesystemOptions.InternalData to FilesystemType.GetFilesystem.
|
||||
//
|
||||
// +stateify savable
|
||||
type InternalFilesystemOptions struct {
|
||||
// RootMerkleFileName is the name of the verity root Merkle tree file.
|
||||
RootMerkleFileName string
|
||||
|
@ -259,6 +265,8 @@ func (fs *filesystem) Release(ctx context.Context) {
|
|||
}
|
||||
|
||||
// dentry implements vfs.DentryImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type dentry struct {
|
||||
vfsd vfs.Dentry
|
||||
|
||||
|
@ -285,7 +293,7 @@ type dentry struct {
|
|||
// and dirents (if not nil) is a cache of dirents as returned by
|
||||
// directoryFDs representing this directory. children is protected by
|
||||
// dirMu.
|
||||
dirMu sync.Mutex
|
||||
dirMu sync.Mutex `state:"nosave"`
|
||||
children map[string]*dentry
|
||||
|
||||
// lowerVD is the VirtualDentry in the underlying file system.
|
||||
|
@ -429,6 +437,8 @@ func (d *dentry) readlink(ctx context.Context) (string, error) {
|
|||
// FileDescription is a wrapper of the underlying lowerFD, with support to build
|
||||
// Merkle trees through the Linux fs-verity API to verify contents read from
|
||||
// lowerFD.
|
||||
//
|
||||
// +stateify savable
|
||||
type fileDescription struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -507,6 +507,10 @@ func (k *Kernel) SaveTo(w wire.Writer) error {
|
|||
// flushMountSourceRefs flushes the MountSources for all mounted filesystems
|
||||
// and open FDs.
|
||||
func (k *Kernel) flushMountSourceRefs(ctx context.Context) error {
|
||||
if VFS2Enabled {
|
||||
return nil // Not relevant.
|
||||
}
|
||||
|
||||
// Flush all mount sources for currently mounted filesystems in each task.
|
||||
flushed := make(map[*fs.MountNamespace]struct{})
|
||||
k.tasks.mu.RLock()
|
||||
|
@ -533,11 +537,6 @@ func (k *Kernel) flushMountSourceRefs(ctx context.Context) error {
|
|||
//
|
||||
// Precondition: Must be called with the kernel paused.
|
||||
func (ts *TaskSet) forEachFDPaused(ctx context.Context, f func(*fs.File, *vfs.FileDescription) error) (err error) {
|
||||
// TODO(gvisor.dev/issue/1663): Add save support for VFS2.
|
||||
if VFS2Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
ts.mu.RLock()
|
||||
defer ts.mu.RUnlock()
|
||||
for t := range ts.Root.tids {
|
||||
|
@ -556,6 +555,10 @@ func (ts *TaskSet) forEachFDPaused(ctx context.Context, f func(*fs.File, *vfs.Fi
|
|||
|
||||
func (ts *TaskSet) flushWritesToFiles(ctx context.Context) error {
|
||||
// TODO(gvisor.dev/issue/1663): Add save support for VFS2.
|
||||
if VFS2Enabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
return ts.forEachFDPaused(ctx, func(file *fs.File, _ *vfs.FileDescription) error {
|
||||
if flags := file.Flags(); !flags.Write {
|
||||
return nil
|
||||
|
|
|
@ -37,6 +37,8 @@ import (
|
|||
|
||||
// SocketVFS2 implements socket.SocketVFS2 (and by extension,
|
||||
// vfs.FileDescriptionImpl) for Unix sockets.
|
||||
//
|
||||
// +stateify savable
|
||||
type SocketVFS2 struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
|
|
|
@ -61,8 +61,10 @@ func (opts SaveOpts) Save(k *kernel.Kernel, w *watchdog.Watchdog) error {
|
|||
log.Infof("Sandbox save started, pausing all tasks.")
|
||||
k.Pause()
|
||||
k.ReceiveTaskStates()
|
||||
defer k.Unpause()
|
||||
defer log.Infof("Tasks resumed after save.")
|
||||
defer func() {
|
||||
k.Unpause()
|
||||
log.Infof("Tasks resumed after save.")
|
||||
}()
|
||||
|
||||
w.Stop()
|
||||
defer w.Start()
|
||||
|
|
|
@ -52,6 +52,8 @@ const (
|
|||
)
|
||||
|
||||
// anonFilesystemType implements FilesystemType.
|
||||
//
|
||||
// +stateify savable
|
||||
type anonFilesystemType struct{}
|
||||
|
||||
// GetFilesystem implements FilesystemType.GetFilesystem.
|
||||
|
@ -69,12 +71,15 @@ func (anonFilesystemType) Name() string {
|
|||
//
|
||||
// Since all Dentries in anonFilesystem are non-directories, all FilesystemImpl
|
||||
// methods that would require an anonDentry to be a directory return ENOTDIR.
|
||||
//
|
||||
// +stateify savable
|
||||
type anonFilesystem struct {
|
||||
vfsfs Filesystem
|
||||
|
||||
devMinor uint32
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type anonDentry struct {
|
||||
vfsd Dentry
|
||||
|
||||
|
|
|
@ -89,6 +89,8 @@ func (d *Dentry) Impl() DentryImpl {
|
|||
// DentryImpl contains implementation details for a Dentry. Implementations of
|
||||
// DentryImpl should contain their associated Dentry by value as their first
|
||||
// field.
|
||||
//
|
||||
// +stateify savable
|
||||
type DentryImpl interface {
|
||||
// IncRef increments the Dentry's reference count. A Dentry with a non-zero
|
||||
// reference count must remain coherent with the state of the filesystem.
|
||||
|
|
|
@ -22,6 +22,8 @@ import (
|
|||
)
|
||||
|
||||
// DeviceKind indicates whether a device is a block or character device.
|
||||
//
|
||||
// +stateify savable
|
||||
type DeviceKind uint32
|
||||
|
||||
const (
|
||||
|
@ -44,6 +46,7 @@ func (kind DeviceKind) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type devTuple struct {
|
||||
kind DeviceKind
|
||||
major uint32
|
||||
|
|
|
@ -27,6 +27,8 @@ import (
|
|||
var epollCycleMu sync.Mutex
|
||||
|
||||
// EpollInstance represents an epoll instance, as described by epoll(7).
|
||||
//
|
||||
// +stateify savable
|
||||
type EpollInstance struct {
|
||||
vfsfd FileDescription
|
||||
FileDescriptionDefaultImpl
|
||||
|
@ -38,11 +40,11 @@ type EpollInstance struct {
|
|||
|
||||
// interest is the set of file descriptors that are registered with the
|
||||
// EpollInstance for monitoring. interest is protected by interestMu.
|
||||
interestMu sync.Mutex
|
||||
interestMu sync.Mutex `state:"nosave"`
|
||||
interest map[epollInterestKey]*epollInterest
|
||||
|
||||
// mu protects fields in registered epollInterests.
|
||||
mu sync.Mutex
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// ready is the set of file descriptors that may be "ready" for I/O. Note
|
||||
// that this must be an ordered list, not a map: "If more than maxevents
|
||||
|
@ -55,6 +57,7 @@ type EpollInstance struct {
|
|||
ready epollInterestList
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type epollInterestKey struct {
|
||||
// file is the registered FileDescription. No reference is held on file;
|
||||
// instead, when the last reference is dropped, FileDescription.DecRef()
|
||||
|
@ -67,6 +70,8 @@ type epollInterestKey struct {
|
|||
}
|
||||
|
||||
// epollInterest represents an EpollInstance's interest in a file descriptor.
|
||||
//
|
||||
// +stateify savable
|
||||
type epollInterest struct {
|
||||
// epoll is the owning EpollInstance. epoll is immutable.
|
||||
epoll *EpollInstance
|
||||
|
|
|
@ -37,11 +37,13 @@ import (
|
|||
// FileDescription methods require that a reference is held.
|
||||
//
|
||||
// FileDescription is analogous to Linux's struct file.
|
||||
//
|
||||
// +stateify savable
|
||||
type FileDescription struct {
|
||||
FileDescriptionRefs
|
||||
|
||||
// flagsMu protects statusFlags and asyncHandler below.
|
||||
flagsMu sync.Mutex
|
||||
flagsMu sync.Mutex `state:"nosave"`
|
||||
|
||||
// statusFlags contains status flags, "initialized by open(2) and possibly
|
||||
// modified by fcntl()" - fcntl(2). statusFlags can be read using atomic
|
||||
|
@ -56,7 +58,7 @@ type FileDescription struct {
|
|||
|
||||
// epolls is the set of epollInterests registered for this FileDescription.
|
||||
// epolls is protected by epollMu.
|
||||
epollMu sync.Mutex
|
||||
epollMu sync.Mutex `state:"nosave"`
|
||||
epolls map[*epollInterest]struct{}
|
||||
|
||||
// vd is the filesystem location at which this FileDescription was opened.
|
||||
|
@ -88,6 +90,8 @@ type FileDescription struct {
|
|||
}
|
||||
|
||||
// FileDescriptionOptions contains options to FileDescription.Init().
|
||||
//
|
||||
// +stateify savable
|
||||
type FileDescriptionOptions struct {
|
||||
// If AllowDirectIO is true, allow O_DIRECT to be set on the file.
|
||||
AllowDirectIO bool
|
||||
|
@ -451,6 +455,8 @@ type FileDescriptionImpl interface {
|
|||
}
|
||||
|
||||
// Dirent holds the information contained in struct linux_dirent64.
|
||||
//
|
||||
// +stateify savable
|
||||
type Dirent struct {
|
||||
// Name is the filename.
|
||||
Name string
|
||||
|
|
|
@ -42,6 +42,8 @@ import (
|
|||
// FileDescriptionDefaultImpl may be embedded by implementations of
|
||||
// FileDescriptionImpl to obtain implementations of many FileDescriptionImpl
|
||||
// methods with default behavior analogous to Linux's.
|
||||
//
|
||||
// +stateify savable
|
||||
type FileDescriptionDefaultImpl struct{}
|
||||
|
||||
// OnClose implements FileDescriptionImpl.OnClose analogously to
|
||||
|
@ -166,6 +168,8 @@ func (FileDescriptionDefaultImpl) RemoveXattr(ctx context.Context, name string)
|
|||
// DirectoryFileDescriptionDefaultImpl may be embedded by implementations of
|
||||
// FileDescriptionImpl that always represent directories to obtain
|
||||
// implementations of non-directory I/O methods that return EISDIR.
|
||||
//
|
||||
// +stateify savable
|
||||
type DirectoryFileDescriptionDefaultImpl struct{}
|
||||
|
||||
// Allocate implements DirectoryFileDescriptionDefaultImpl.Allocate.
|
||||
|
@ -196,6 +200,8 @@ func (DirectoryFileDescriptionDefaultImpl) Write(ctx context.Context, src userme
|
|||
// DentryMetadataFileDescriptionImpl may be embedded by implementations of
|
||||
// FileDescriptionImpl for which FileDescriptionOptions.UseDentryMetadata is
|
||||
// true to obtain implementations of Stat and SetStat that panic.
|
||||
//
|
||||
// +stateify savable
|
||||
type DentryMetadataFileDescriptionImpl struct{}
|
||||
|
||||
// Stat implements FileDescriptionImpl.Stat.
|
||||
|
@ -210,12 +216,16 @@ func (DentryMetadataFileDescriptionImpl) SetStat(ctx context.Context, opts SetSt
|
|||
|
||||
// DynamicBytesSource represents a data source for a
|
||||
// DynamicBytesFileDescriptionImpl.
|
||||
//
|
||||
// +stateify savable
|
||||
type DynamicBytesSource interface {
|
||||
// Generate writes the file's contents to buf.
|
||||
Generate(ctx context.Context, buf *bytes.Buffer) error
|
||||
}
|
||||
|
||||
// StaticData implements DynamicBytesSource over a static string.
|
||||
//
|
||||
// +stateify savable
|
||||
type StaticData struct {
|
||||
Data string
|
||||
}
|
||||
|
@ -242,14 +252,24 @@ type WritableDynamicBytesSource interface {
|
|||
//
|
||||
// DynamicBytesFileDescriptionImpl.SetDataSource() must be called before first
|
||||
// use.
|
||||
//
|
||||
// +stateify savable
|
||||
type DynamicBytesFileDescriptionImpl struct {
|
||||
data DynamicBytesSource // immutable
|
||||
mu sync.Mutex // protects the following fields
|
||||
buf bytes.Buffer
|
||||
mu sync.Mutex `state:"nosave"` // protects the following fields
|
||||
buf bytes.Buffer `state:".([]byte)"`
|
||||
off int64
|
||||
lastRead int64 // offset at which the last Read, PRead, or Seek ended
|
||||
}
|
||||
|
||||
func (fd *DynamicBytesFileDescriptionImpl) saveBuf() []byte {
|
||||
return fd.buf.Bytes()
|
||||
}
|
||||
|
||||
func (fd *DynamicBytesFileDescriptionImpl) loadBuf(p []byte) {
|
||||
fd.buf.Write(p)
|
||||
}
|
||||
|
||||
// SetDataSource must be called exactly once on fd before first use.
|
||||
func (fd *DynamicBytesFileDescriptionImpl) SetDataSource(data DynamicBytesSource) {
|
||||
fd.data = data
|
||||
|
@ -382,6 +402,8 @@ func GenericConfigureMMap(fd *FileDescription, m memmap.Mappable, opts *memmap.M
|
|||
|
||||
// LockFD may be used by most implementations of FileDescriptionImpl.Lock*
|
||||
// functions. Caller must call Init().
|
||||
//
|
||||
// +stateify savable
|
||||
type LockFD struct {
|
||||
locks *FileLocks
|
||||
}
|
||||
|
@ -409,6 +431,8 @@ func (fd *LockFD) UnlockBSD(ctx context.Context, uid fslock.UniqueID) error {
|
|||
|
||||
// NoLockFD implements Lock*/Unlock* portion of FileDescriptionImpl interface
|
||||
// returning ENOLCK.
|
||||
//
|
||||
// +stateify savable
|
||||
type NoLockFD struct{}
|
||||
|
||||
// LockBSD implements vfs.FileDescriptionImpl.LockBSD.
|
||||
|
|
|
@ -506,6 +506,8 @@ type FilesystemImpl interface {
|
|||
|
||||
// PrependPathAtVFSRootError is returned by implementations of
|
||||
// FilesystemImpl.PrependPath() when they encounter the contextual VFS root.
|
||||
//
|
||||
// +stateify savable
|
||||
type PrependPathAtVFSRootError struct{}
|
||||
|
||||
// Error implements error.Error.
|
||||
|
@ -516,6 +518,8 @@ func (PrependPathAtVFSRootError) Error() string {
|
|||
// PrependPathAtNonMountRootError is returned by implementations of
|
||||
// FilesystemImpl.PrependPath() when they encounter an independent ancestor
|
||||
// Dentry that is not the Mount root.
|
||||
//
|
||||
// +stateify savable
|
||||
type PrependPathAtNonMountRootError struct{}
|
||||
|
||||
// Error implements error.Error.
|
||||
|
@ -526,6 +530,8 @@ func (PrependPathAtNonMountRootError) Error() string {
|
|||
// PrependPathSyntheticError is returned by implementations of
|
||||
// FilesystemImpl.PrependPath() for which prepended names do not represent real
|
||||
// paths.
|
||||
//
|
||||
// +stateify savable
|
||||
type PrependPathSyntheticError struct{}
|
||||
|
||||
// Error implements error.Error.
|
||||
|
|
|
@ -55,6 +55,8 @@ type registeredFilesystemType struct {
|
|||
|
||||
// RegisterFilesystemTypeOptions contains options to
|
||||
// VirtualFilesystem.RegisterFilesystem().
|
||||
//
|
||||
// +stateify savable
|
||||
type RegisterFilesystemTypeOptions struct {
|
||||
// AllowUserMount determines whether users are allowed to mount a file system
|
||||
// of this type, i.e. through mount(2). If AllowUserMount is true, allow calls
|
||||
|
|
|
@ -27,6 +27,8 @@ import (
|
|||
)
|
||||
|
||||
// Dentry is a required type parameter that is a struct with the given fields.
|
||||
//
|
||||
// +stateify savable
|
||||
type Dentry struct {
|
||||
// vfsd is the embedded vfs.Dentry corresponding to this vfs.DentryImpl.
|
||||
vfsd vfs.Dentry
|
||||
|
|
|
@ -37,6 +37,8 @@ const inotifyEventBaseSize = 16
|
|||
//
|
||||
// The way events are labelled appears somewhat arbitrary, but they must match
|
||||
// Linux so that IN_EXCL_UNLINK behaves as it does in Linux.
|
||||
//
|
||||
// +stateify savable
|
||||
type EventType uint8
|
||||
|
||||
// PathEvent and InodeEvent correspond to FSNOTIFY_EVENT_PATH and
|
||||
|
|
|
@ -33,6 +33,8 @@ import (
|
|||
// Note that in Linux these two types of locks are _not_ cooperative, because
|
||||
// race and deadlock conditions make merging them prohibitive. We do the same
|
||||
// and keep them oblivious to each other.
|
||||
//
|
||||
// +stateify savable
|
||||
type FileLocks struct {
|
||||
// bsd is a set of BSD-style advisory file wide locks, see flock(2).
|
||||
bsd fslock.Locks
|
||||
|
|
|
@ -65,7 +65,7 @@ type Mount struct {
|
|||
//
|
||||
// Invariant: key.parent != nil iff key.point != nil. key.point belongs to
|
||||
// key.parent.fs.
|
||||
key mountKey
|
||||
key mountKey `state:".(VirtualDentry)"`
|
||||
|
||||
// ns is the namespace in which this Mount was mounted. ns is protected by
|
||||
// VirtualFilesystem.mountMu.
|
||||
|
@ -345,6 +345,7 @@ func (vfs *VirtualFilesystem) UmountAt(ctx context.Context, creds *auth.Credenti
|
|||
return nil
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type umountRecursiveOptions struct {
|
||||
// If eager is true, ensure that future calls to Mount.tryIncMountedRef()
|
||||
// on umounted mounts fail.
|
||||
|
@ -414,7 +415,7 @@ func (vfs *VirtualFilesystem) connectLocked(mnt *Mount, vd VirtualDentry, mntns
|
|||
}
|
||||
}
|
||||
mnt.IncRef() // dropped by callers of umountRecursiveLocked
|
||||
mnt.storeKey(vd)
|
||||
mnt.setKey(vd)
|
||||
if vd.mount.children == nil {
|
||||
vd.mount.children = make(map[*Mount]struct{})
|
||||
}
|
||||
|
@ -439,13 +440,13 @@ func (vfs *VirtualFilesystem) connectLocked(mnt *Mount, vd VirtualDentry, mntns
|
|||
// * vfs.mounts.seq must be in a writer critical section.
|
||||
// * mnt.parent() != nil.
|
||||
func (vfs *VirtualFilesystem) disconnectLocked(mnt *Mount) VirtualDentry {
|
||||
vd := mnt.loadKey()
|
||||
vd := mnt.getKey()
|
||||
if checkInvariants {
|
||||
if vd.mount != nil {
|
||||
panic("VFS.disconnectLocked called on disconnected mount")
|
||||
}
|
||||
}
|
||||
mnt.storeKey(VirtualDentry{})
|
||||
mnt.loadKey(VirtualDentry{})
|
||||
delete(vd.mount.children, mnt)
|
||||
atomic.AddUint32(&vd.dentry.mounts, math.MaxUint32) // -1
|
||||
mnt.ns.mountpoints[vd.dentry]--
|
||||
|
|
|
@ -38,7 +38,7 @@ func TestMountTableInsertLookup(t *testing.T) {
|
|||
mt.Init()
|
||||
|
||||
mount := &Mount{}
|
||||
mount.storeKey(VirtualDentry{&Mount{}, &Dentry{}})
|
||||
mount.setKey(VirtualDentry{&Mount{}, &Dentry{}})
|
||||
mt.Insert(mount)
|
||||
|
||||
if m := mt.Lookup(mount.parent(), mount.point()); m != mount {
|
||||
|
@ -79,7 +79,7 @@ const enableComparativeBenchmarks = false
|
|||
|
||||
func newBenchMount() *Mount {
|
||||
mount := &Mount{}
|
||||
mount.storeKey(VirtualDentry{&Mount{}, &Dentry{}})
|
||||
mount.loadKey(VirtualDentry{&Mount{}, &Dentry{}})
|
||||
return mount
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ func BenchmarkMountTableParallelLookup(b *testing.B) {
|
|||
for i := 0; i < numMounts; i++ {
|
||||
mount := newBenchMount()
|
||||
mt.Insert(mount)
|
||||
keys = append(keys, mount.loadKey())
|
||||
keys = append(keys, mount.saveKey())
|
||||
}
|
||||
|
||||
var ready sync.WaitGroup
|
||||
|
@ -146,7 +146,7 @@ func BenchmarkMountMapParallelLookup(b *testing.B) {
|
|||
keys := make([]VirtualDentry, 0, numMounts)
|
||||
for i := 0; i < numMounts; i++ {
|
||||
mount := newBenchMount()
|
||||
key := mount.loadKey()
|
||||
key := mount.saveKey()
|
||||
ms[key] = mount
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ func BenchmarkMountSyncMapParallelLookup(b *testing.B) {
|
|||
keys := make([]VirtualDentry, 0, numMounts)
|
||||
for i := 0; i < numMounts; i++ {
|
||||
mount := newBenchMount()
|
||||
key := mount.loadKey()
|
||||
key := mount.getKey()
|
||||
ms.Store(key, mount)
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ func BenchmarkMountMapNegativeLookup(b *testing.B) {
|
|||
ms := make(map[VirtualDentry]*Mount)
|
||||
for i := 0; i < numMounts; i++ {
|
||||
mount := newBenchMount()
|
||||
ms[mount.loadKey()] = mount
|
||||
ms[mount.getKey()] = mount
|
||||
}
|
||||
negkeys := make([]VirtualDentry, 0, numMounts)
|
||||
for i := 0; i < numMounts; i++ {
|
||||
|
@ -318,7 +318,7 @@ func BenchmarkMountSyncMapNegativeLookup(b *testing.B) {
|
|||
var ms sync.Map
|
||||
for i := 0; i < numMounts; i++ {
|
||||
mount := newBenchMount()
|
||||
ms.Store(mount.loadKey(), mount)
|
||||
ms.Store(mount.saveKey(), mount)
|
||||
}
|
||||
negkeys := make([]VirtualDentry, 0, numMounts)
|
||||
for i := 0; i < numMounts; i++ {
|
||||
|
@ -372,7 +372,7 @@ func BenchmarkMountMapInsert(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
for i := range mounts {
|
||||
mount := mounts[i]
|
||||
ms[mount.loadKey()] = mount
|
||||
ms[mount.saveKey()] = mount
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,7 +392,7 @@ func BenchmarkMountSyncMapInsert(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
for i := range mounts {
|
||||
mount := mounts[i]
|
||||
ms.Store(mount.loadKey(), mount)
|
||||
ms.Store(mount.saveKey(), mount)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,13 +425,13 @@ func BenchmarkMountMapRemove(b *testing.B) {
|
|||
ms := make(map[VirtualDentry]*Mount)
|
||||
for i := range mounts {
|
||||
mount := mounts[i]
|
||||
ms[mount.loadKey()] = mount
|
||||
ms[mount.saveKey()] = mount
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := range mounts {
|
||||
mount := mounts[i]
|
||||
delete(ms, mount.loadKey())
|
||||
delete(ms, mount.saveKey())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,12 +447,12 @@ func BenchmarkMountSyncMapRemove(b *testing.B) {
|
|||
var ms sync.Map
|
||||
for i := range mounts {
|
||||
mount := mounts[i]
|
||||
ms.Store(mount.loadKey(), mount)
|
||||
ms.Store(mount.saveKey(), mount)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := range mounts {
|
||||
mount := mounts[i]
|
||||
ms.Delete(mount.loadKey())
|
||||
ms.Delete(mount.saveKey())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ import (
|
|||
// structurally identical to VirtualDentry, but stores its fields as
|
||||
// unsafe.Pointer since mutators synchronize with VFS path traversal using
|
||||
// seqcounts.
|
||||
//
|
||||
// This is explicitly not savable.
|
||||
type mountKey struct {
|
||||
parent unsafe.Pointer // *Mount
|
||||
point unsafe.Pointer // *Dentry
|
||||
|
@ -47,19 +49,23 @@ func (mnt *Mount) point() *Dentry {
|
|||
return (*Dentry)(atomic.LoadPointer(&mnt.key.point))
|
||||
}
|
||||
|
||||
func (mnt *Mount) loadKey() VirtualDentry {
|
||||
func (mnt *Mount) getKey() VirtualDentry {
|
||||
return VirtualDentry{
|
||||
mount: mnt.parent(),
|
||||
dentry: mnt.point(),
|
||||
}
|
||||
}
|
||||
|
||||
func (mnt *Mount) saveKey() VirtualDentry { return mnt.getKey() }
|
||||
|
||||
// Invariant: mnt.key.parent == nil. vd.Ok().
|
||||
func (mnt *Mount) storeKey(vd VirtualDentry) {
|
||||
func (mnt *Mount) setKey(vd VirtualDentry) {
|
||||
atomic.StorePointer(&mnt.key.parent, unsafe.Pointer(vd.mount))
|
||||
atomic.StorePointer(&mnt.key.point, unsafe.Pointer(vd.dentry))
|
||||
}
|
||||
|
||||
func (mnt *Mount) loadKey(vd VirtualDentry) { mnt.setKey(vd) }
|
||||
|
||||
// mountTable maps (mount parent, mount point) pairs to mounts. It supports
|
||||
// efficient concurrent lookup, even in the presence of concurrent mutators
|
||||
// (provided mutation is sufficiently uncommon).
|
||||
|
@ -92,6 +98,7 @@ type mountTable struct {
|
|||
// length and cap in separate uint32s) for ~free.
|
||||
size uint64
|
||||
|
||||
// FIXME(gvisor.dev/issue/1663): Slots need to be saved.
|
||||
slots unsafe.Pointer `state:"nosave"` // []mountSlot; never nil after Init
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ import (
|
|||
|
||||
// GetDentryOptions contains options to VirtualFilesystem.GetDentryAt() and
|
||||
// FilesystemImpl.GetDentryAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type GetDentryOptions struct {
|
||||
// If CheckSearchable is true, FilesystemImpl.GetDentryAt() must check that
|
||||
// the returned Dentry is a directory for which creds has search
|
||||
|
@ -30,6 +32,8 @@ type GetDentryOptions struct {
|
|||
|
||||
// MkdirOptions contains options to VirtualFilesystem.MkdirAt() and
|
||||
// FilesystemImpl.MkdirAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type MkdirOptions struct {
|
||||
// Mode is the file mode bits for the created directory.
|
||||
Mode linux.FileMode
|
||||
|
@ -56,6 +60,8 @@ type MkdirOptions struct {
|
|||
|
||||
// MknodOptions contains options to VirtualFilesystem.MknodAt() and
|
||||
// FilesystemImpl.MknodAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type MknodOptions struct {
|
||||
// Mode is the file type and mode bits for the created file.
|
||||
Mode linux.FileMode
|
||||
|
@ -72,6 +78,8 @@ type MknodOptions struct {
|
|||
|
||||
// MountFlags contains flags as specified for mount(2), e.g. MS_NOEXEC.
|
||||
// MS_RDONLY is not part of MountFlags because it's tracked in Mount.writers.
|
||||
//
|
||||
// +stateify savable
|
||||
type MountFlags struct {
|
||||
// NoExec is equivalent to MS_NOEXEC.
|
||||
NoExec bool
|
||||
|
@ -93,6 +101,8 @@ type MountFlags struct {
|
|||
}
|
||||
|
||||
// MountOptions contains options to VirtualFilesystem.MountAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type MountOptions struct {
|
||||
// Flags contains flags as specified for mount(2), e.g. MS_NOEXEC.
|
||||
Flags MountFlags
|
||||
|
@ -112,6 +122,8 @@ type MountOptions struct {
|
|||
|
||||
// OpenOptions contains options to VirtualFilesystem.OpenAt() and
|
||||
// FilesystemImpl.OpenAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type OpenOptions struct {
|
||||
// Flags contains access mode and flags as specified for open(2).
|
||||
//
|
||||
|
@ -137,6 +149,8 @@ type OpenOptions struct {
|
|||
// ReadOptions contains options to FileDescription.PRead(),
|
||||
// FileDescriptionImpl.PRead(), FileDescription.Read(), and
|
||||
// FileDescriptionImpl.Read().
|
||||
//
|
||||
// +stateify savable
|
||||
type ReadOptions struct {
|
||||
// Flags contains flags as specified for preadv2(2).
|
||||
Flags uint32
|
||||
|
@ -144,6 +158,8 @@ type ReadOptions struct {
|
|||
|
||||
// RenameOptions contains options to VirtualFilesystem.RenameAt() and
|
||||
// FilesystemImpl.RenameAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type RenameOptions struct {
|
||||
// Flags contains flags as specified for renameat2(2).
|
||||
Flags uint32
|
||||
|
@ -155,6 +171,8 @@ type RenameOptions struct {
|
|||
// SetStatOptions contains options to VirtualFilesystem.SetStatAt(),
|
||||
// FilesystemImpl.SetStatAt(), FileDescription.SetStat(), and
|
||||
// FileDescriptionImpl.SetStat().
|
||||
//
|
||||
// +stateify savable
|
||||
type SetStatOptions struct {
|
||||
// Stat is the metadata that should be set. Only fields indicated by
|
||||
// Stat.Mask should be set.
|
||||
|
@ -176,6 +194,8 @@ type SetStatOptions struct {
|
|||
|
||||
// BoundEndpointOptions contains options to VirtualFilesystem.BoundEndpointAt()
|
||||
// and FilesystemImpl.BoundEndpointAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type BoundEndpointOptions struct {
|
||||
// Addr is the path of the file whose socket endpoint is being retrieved.
|
||||
// It is generally irrelevant: most endpoints are stored at a dentry that
|
||||
|
@ -195,6 +215,8 @@ type BoundEndpointOptions struct {
|
|||
// GetXattrOptions contains options to VirtualFilesystem.GetXattrAt(),
|
||||
// FilesystemImpl.GetXattrAt(), FileDescription.GetXattr(), and
|
||||
// FileDescriptionImpl.GetXattr().
|
||||
//
|
||||
// +stateify savable
|
||||
type GetXattrOptions struct {
|
||||
// Name is the name of the extended attribute to retrieve.
|
||||
Name string
|
||||
|
@ -209,6 +231,8 @@ type GetXattrOptions struct {
|
|||
// SetXattrOptions contains options to VirtualFilesystem.SetXattrAt(),
|
||||
// FilesystemImpl.SetXattrAt(), FileDescription.SetXattr(), and
|
||||
// FileDescriptionImpl.SetXattr().
|
||||
//
|
||||
// +stateify savable
|
||||
type SetXattrOptions struct {
|
||||
// Name is the name of the extended attribute being mutated.
|
||||
Name string
|
||||
|
@ -223,6 +247,8 @@ type SetXattrOptions struct {
|
|||
// StatOptions contains options to VirtualFilesystem.StatAt(),
|
||||
// FilesystemImpl.StatAt(), FileDescription.Stat(), and
|
||||
// FileDescriptionImpl.Stat().
|
||||
//
|
||||
// +stateify savable
|
||||
type StatOptions struct {
|
||||
// Mask is the set of fields in the returned Statx that the FilesystemImpl
|
||||
// or FileDescriptionImpl should provide. Bits are as in linux.Statx.Mask.
|
||||
|
@ -240,6 +266,8 @@ type StatOptions struct {
|
|||
}
|
||||
|
||||
// UmountOptions contains options to VirtualFilesystem.UmountAt().
|
||||
//
|
||||
// +stateify savable
|
||||
type UmountOptions struct {
|
||||
// Flags contains flags as specified for umount2(2).
|
||||
Flags uint32
|
||||
|
@ -248,6 +276,8 @@ type UmountOptions struct {
|
|||
// WriteOptions contains options to FileDescription.PWrite(),
|
||||
// FileDescriptionImpl.PWrite(), FileDescription.Write(), and
|
||||
// FileDescriptionImpl.Write().
|
||||
//
|
||||
// +stateify savable
|
||||
type WriteOptions struct {
|
||||
// Flags contains flags as specified for pwritev2(2).
|
||||
Flags uint32
|
||||
|
|
|
@ -26,6 +26,8 @@ import (
|
|||
)
|
||||
|
||||
// AccessTypes is a bitmask of Unix file permissions.
|
||||
//
|
||||
// +stateify savable
|
||||
type AccessTypes uint16
|
||||
|
||||
// Bits in AccessTypes.
|
||||
|
|
|
@ -35,6 +35,8 @@ import (
|
|||
// FilesystemImpl methods.
|
||||
//
|
||||
// ResolvingPath is loosely analogous to Linux's struct nameidata.
|
||||
//
|
||||
// +stateify savable
|
||||
type ResolvingPath struct {
|
||||
vfs *VirtualFilesystem
|
||||
root VirtualDentry // refs borrowed from PathOperation
|
||||
|
@ -88,6 +90,7 @@ func init() {
|
|||
// so error "constants" are really mutable vars, necessitating somewhat
|
||||
// expensive interface object comparisons.
|
||||
|
||||
// +stateify savable
|
||||
type resolveMountRootOrJumpError struct{}
|
||||
|
||||
// Error implements error.Error.
|
||||
|
@ -95,6 +98,7 @@ func (resolveMountRootOrJumpError) Error() string {
|
|||
return "resolving mount root or jump"
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type resolveMountPointError struct{}
|
||||
|
||||
// Error implements error.Error.
|
||||
|
@ -102,6 +106,7 @@ func (resolveMountPointError) Error() string {
|
|||
return "resolving mount point"
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type resolveAbsSymlinkError struct{}
|
||||
|
||||
// Error implements error.Error.
|
||||
|
|
|
@ -163,6 +163,8 @@ func (vfs *VirtualFilesystem) Init(ctx context.Context) error {
|
|||
// PathOperation is passed to VFS methods by pointer to reduce memory copying:
|
||||
// it's somewhat large and should never escape. (Options structs are passed by
|
||||
// pointer to VFS and FileDescription methods for the same reason.)
|
||||
//
|
||||
// +stateify savable
|
||||
type PathOperation struct {
|
||||
// Root is the VFS root. References on Root are borrowed from the provider
|
||||
// of the PathOperation.
|
||||
|
|
|
@ -107,6 +107,14 @@ func lookupNameFields(typ reflect.Type) (string, []string, bool) {
|
|||
}
|
||||
return name, nil, true
|
||||
}
|
||||
// Sanity check the type.
|
||||
if raceEnabled {
|
||||
if _, ok := reverseTypeDatabase[typ]; !ok {
|
||||
// The type was not registered? Must be an embedded
|
||||
// structure or something else.
|
||||
return "", nil, false
|
||||
}
|
||||
}
|
||||
// Extract the name from the object.
|
||||
name := t.StateTypeName()
|
||||
fields := t.StateFields()
|
||||
|
@ -313,6 +321,9 @@ var primitiveTypeDatabase = func() map[string]reflect.Type {
|
|||
// globalTypeDatabase is used for dispatching interfaces on decode.
|
||||
var globalTypeDatabase = map[string]reflect.Type{}
|
||||
|
||||
// reverseTypeDatabase is a reverse mapping.
|
||||
var reverseTypeDatabase = map[reflect.Type]string{}
|
||||
|
||||
// Register registers a type.
|
||||
//
|
||||
// This must be called on init and only done once.
|
||||
|
@ -358,4 +369,7 @@ func Register(t Type) {
|
|||
Failf("conflicting name for %T: matches interfaceType", t)
|
||||
}
|
||||
globalTypeDatabase[name] = typ
|
||||
if raceEnabled {
|
||||
reverseTypeDatabase[typ] = name
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue