diff options
Diffstat (limited to 'pkg/sentry/fsimpl/gofer')
-rw-r--r-- | pkg/sentry/fsimpl/gofer/directory.go | 3 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/gofer/gofer.go | 39 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/gofer/gofer_state_autogen.go | 488 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/gofer/handle.go | 2 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/gofer/regular_file.go | 7 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/gofer/socket.go | 4 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/gofer/special_file.go | 6 |
7 files changed, 531 insertions, 18 deletions
diff --git a/pkg/sentry/fsimpl/gofer/directory.go b/pkg/sentry/fsimpl/gofer/directory.go index 91d2ae199..18c884b59 100644 --- a/pkg/sentry/fsimpl/gofer/directory.go +++ b/pkg/sentry/fsimpl/gofer/directory.go @@ -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 } diff --git a/pkg/sentry/fsimpl/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go index aaad9c0d9..8608471f8 100644 --- a/pkg/sentry/fsimpl/gofer/gofer.go +++ b/pkg/sentry/fsimpl/gofer/gofer.go @@ -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 { diff --git a/pkg/sentry/fsimpl/gofer/gofer_state_autogen.go b/pkg/sentry/fsimpl/gofer/gofer_state_autogen.go index 19b1eef9e..7831e1830 100644 --- a/pkg/sentry/fsimpl/gofer/gofer_state_autogen.go +++ b/pkg/sentry/fsimpl/gofer/gofer_state_autogen.go @@ -58,7 +58,495 @@ func (x *dentryEntry) StateLoad(m state.Source) { m.Load(1, &x.prev) } +func (x *directoryFD) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.directoryFD" +} + +func (x *directoryFD) StateFields() []string { + return []string{ + "fileDescription", + "DirectoryFileDescriptionDefaultImpl", + "off", + "dirents", + } +} + +func (x *directoryFD) beforeSave() {} + +func (x *directoryFD) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.fileDescription) + m.Save(1, &x.DirectoryFileDescriptionDefaultImpl) + m.Save(2, &x.off) + m.Save(3, &x.dirents) +} + +func (x *directoryFD) afterLoad() {} + +func (x *directoryFD) StateLoad(m state.Source) { + m.Load(0, &x.fileDescription) + m.Load(1, &x.DirectoryFileDescriptionDefaultImpl) + m.Load(2, &x.off) + m.Load(3, &x.dirents) +} + +func (x *FilesystemType) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.FilesystemType" +} + +func (x *FilesystemType) StateFields() []string { + return []string{} +} + +func (x *FilesystemType) beforeSave() {} + +func (x *FilesystemType) StateSave(m state.Sink) { + x.beforeSave() +} + +func (x *FilesystemType) afterLoad() {} + +func (x *FilesystemType) StateLoad(m state.Source) { +} + +func (x *filesystem) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.filesystem" +} + +func (x *filesystem) StateFields() []string { + return []string{ + "vfsfs", + "mfp", + "opts", + "iopts", + "clock", + "devMinor", + "cachedDentries", + "cachedDentriesLen", + "syncableDentries", + "specialFileFDs", + "syntheticSeq", + } +} + +func (x *filesystem) beforeSave() {} + +func (x *filesystem) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.vfsfs) + m.Save(1, &x.mfp) + m.Save(2, &x.opts) + m.Save(3, &x.iopts) + m.Save(4, &x.clock) + m.Save(5, &x.devMinor) + m.Save(6, &x.cachedDentries) + m.Save(7, &x.cachedDentriesLen) + m.Save(8, &x.syncableDentries) + m.Save(9, &x.specialFileFDs) + m.Save(10, &x.syntheticSeq) +} + +func (x *filesystem) afterLoad() {} + +func (x *filesystem) StateLoad(m state.Source) { + m.Load(0, &x.vfsfs) + m.Load(1, &x.mfp) + m.Load(2, &x.opts) + m.Load(3, &x.iopts) + m.Load(4, &x.clock) + m.Load(5, &x.devMinor) + m.Load(6, &x.cachedDentries) + m.Load(7, &x.cachedDentriesLen) + m.Load(8, &x.syncableDentries) + m.Load(9, &x.specialFileFDs) + m.Load(10, &x.syntheticSeq) +} + +func (x *inodeNumber) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.inodeNumber" +} + +func (x *inodeNumber) StateFields() []string { + return nil +} + +func (x *filesystemOptions) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.filesystemOptions" +} + +func (x *filesystemOptions) StateFields() []string { + return []string{ + "fd", + "aname", + "interop", + "dfltuid", + "dfltgid", + "msize", + "version", + "maxCachedDentries", + "forcePageCache", + "limitHostFDTranslation", + "overlayfsStaleRead", + "regularFilesUseSpecialFileFD", + } +} + +func (x *filesystemOptions) beforeSave() {} + +func (x *filesystemOptions) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.fd) + m.Save(1, &x.aname) + m.Save(2, &x.interop) + m.Save(3, &x.dfltuid) + m.Save(4, &x.dfltgid) + m.Save(5, &x.msize) + m.Save(6, &x.version) + m.Save(7, &x.maxCachedDentries) + m.Save(8, &x.forcePageCache) + m.Save(9, &x.limitHostFDTranslation) + m.Save(10, &x.overlayfsStaleRead) + m.Save(11, &x.regularFilesUseSpecialFileFD) +} + +func (x *filesystemOptions) afterLoad() {} + +func (x *filesystemOptions) StateLoad(m state.Source) { + m.Load(0, &x.fd) + m.Load(1, &x.aname) + m.Load(2, &x.interop) + m.Load(3, &x.dfltuid) + m.Load(4, &x.dfltgid) + m.Load(5, &x.msize) + m.Load(6, &x.version) + m.Load(7, &x.maxCachedDentries) + m.Load(8, &x.forcePageCache) + m.Load(9, &x.limitHostFDTranslation) + m.Load(10, &x.overlayfsStaleRead) + m.Load(11, &x.regularFilesUseSpecialFileFD) +} + +func (x *InteropMode) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.InteropMode" +} + +func (x *InteropMode) StateFields() []string { + return nil +} + +func (x *InternalFilesystemOptions) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.InternalFilesystemOptions" +} + +func (x *InternalFilesystemOptions) StateFields() []string { + return []string{ + "LeakConnection", + "OpenSocketsByConnecting", + } +} + +func (x *InternalFilesystemOptions) beforeSave() {} + +func (x *InternalFilesystemOptions) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.LeakConnection) + m.Save(1, &x.OpenSocketsByConnecting) +} + +func (x *InternalFilesystemOptions) afterLoad() {} + +func (x *InternalFilesystemOptions) StateLoad(m state.Source) { + m.Load(0, &x.LeakConnection) + m.Load(1, &x.OpenSocketsByConnecting) +} + +func (x *dentry) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.dentry" +} + +func (x *dentry) StateFields() []string { + return []string{ + "vfsd", + "refs", + "fs", + "parent", + "name", + "deleted", + "cached", + "dentryEntry", + "children", + "syntheticChildren", + "dirents", + "ino", + "mode", + "uid", + "gid", + "blockSize", + "atime", + "mtime", + "ctime", + "btime", + "size", + "atimeDirty", + "mtimeDirty", + "nlink", + "mappings", + "hostFD", + "cache", + "dirty", + "pf", + "haveTarget", + "target", + "endpoint", + "pipe", + "locks", + "watches", + } +} + +func (x *dentry) beforeSave() {} + +func (x *dentry) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.vfsd) + m.Save(1, &x.refs) + m.Save(2, &x.fs) + m.Save(3, &x.parent) + m.Save(4, &x.name) + m.Save(5, &x.deleted) + m.Save(6, &x.cached) + m.Save(7, &x.dentryEntry) + m.Save(8, &x.children) + m.Save(9, &x.syntheticChildren) + m.Save(10, &x.dirents) + m.Save(11, &x.ino) + m.Save(12, &x.mode) + m.Save(13, &x.uid) + m.Save(14, &x.gid) + m.Save(15, &x.blockSize) + m.Save(16, &x.atime) + m.Save(17, &x.mtime) + m.Save(18, &x.ctime) + m.Save(19, &x.btime) + m.Save(20, &x.size) + m.Save(21, &x.atimeDirty) + m.Save(22, &x.mtimeDirty) + m.Save(23, &x.nlink) + m.Save(24, &x.mappings) + m.Save(25, &x.hostFD) + m.Save(26, &x.cache) + m.Save(27, &x.dirty) + m.Save(28, &x.pf) + m.Save(29, &x.haveTarget) + m.Save(30, &x.target) + m.Save(31, &x.endpoint) + m.Save(32, &x.pipe) + m.Save(33, &x.locks) + m.Save(34, &x.watches) +} + +func (x *dentry) afterLoad() {} + +func (x *dentry) StateLoad(m state.Source) { + m.Load(0, &x.vfsd) + m.Load(1, &x.refs) + m.Load(2, &x.fs) + m.Load(3, &x.parent) + m.Load(4, &x.name) + m.Load(5, &x.deleted) + m.Load(6, &x.cached) + m.Load(7, &x.dentryEntry) + m.Load(8, &x.children) + m.Load(9, &x.syntheticChildren) + m.Load(10, &x.dirents) + m.Load(11, &x.ino) + m.Load(12, &x.mode) + m.Load(13, &x.uid) + m.Load(14, &x.gid) + m.Load(15, &x.blockSize) + m.Load(16, &x.atime) + m.Load(17, &x.mtime) + m.Load(18, &x.ctime) + m.Load(19, &x.btime) + m.Load(20, &x.size) + m.Load(21, &x.atimeDirty) + m.Load(22, &x.mtimeDirty) + m.Load(23, &x.nlink) + m.Load(24, &x.mappings) + m.Load(25, &x.hostFD) + m.Load(26, &x.cache) + m.Load(27, &x.dirty) + m.Load(28, &x.pf) + m.Load(29, &x.haveTarget) + m.Load(30, &x.target) + m.Load(31, &x.endpoint) + m.Load(32, &x.pipe) + m.Load(33, &x.locks) + m.Load(34, &x.watches) +} + +func (x *fileDescription) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.fileDescription" +} + +func (x *fileDescription) StateFields() []string { + return []string{ + "vfsfd", + "FileDescriptionDefaultImpl", + "LockFD", + } +} + +func (x *fileDescription) beforeSave() {} + +func (x *fileDescription) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.vfsfd) + m.Save(1, &x.FileDescriptionDefaultImpl) + m.Save(2, &x.LockFD) +} + +func (x *fileDescription) afterLoad() {} + +func (x *fileDescription) StateLoad(m state.Source) { + m.Load(0, &x.vfsfd) + m.Load(1, &x.FileDescriptionDefaultImpl) + m.Load(2, &x.LockFD) +} + +func (x *regularFileFD) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.regularFileFD" +} + +func (x *regularFileFD) StateFields() []string { + return []string{ + "fileDescription", + "off", + } +} + +func (x *regularFileFD) beforeSave() {} + +func (x *regularFileFD) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.fileDescription) + m.Save(1, &x.off) +} + +func (x *regularFileFD) afterLoad() {} + +func (x *regularFileFD) StateLoad(m state.Source) { + m.Load(0, &x.fileDescription) + m.Load(1, &x.off) +} + +func (x *dentryPlatformFile) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.dentryPlatformFile" +} + +func (x *dentryPlatformFile) StateFields() []string { + return []string{ + "dentry", + "fdRefs", + "hostFileMapper", + } +} + +func (x *dentryPlatformFile) beforeSave() {} + +func (x *dentryPlatformFile) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.dentry) + m.Save(1, &x.fdRefs) + m.Save(2, &x.hostFileMapper) +} + +func (x *dentryPlatformFile) afterLoad() {} + +func (x *dentryPlatformFile) StateLoad(m state.Source) { + m.Load(0, &x.dentry) + m.Load(1, &x.fdRefs) + m.Load(2, &x.hostFileMapper) +} + +func (x *endpoint) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.endpoint" +} + +func (x *endpoint) StateFields() []string { + return []string{ + "dentry", + "path", + } +} + +func (x *endpoint) beforeSave() {} + +func (x *endpoint) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.dentry) + m.Save(1, &x.path) +} + +func (x *endpoint) afterLoad() {} + +func (x *endpoint) StateLoad(m state.Source) { + m.Load(0, &x.dentry) + m.Load(1, &x.path) +} + +func (x *specialFileFD) StateTypeName() string { + return "pkg/sentry/fsimpl/gofer.specialFileFD" +} + +func (x *specialFileFD) StateFields() []string { + return []string{ + "fileDescription", + "isRegularFile", + "seekable", + "haveQueue", + "queue", + "off", + } +} + +func (x *specialFileFD) beforeSave() {} + +func (x *specialFileFD) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.fileDescription) + m.Save(1, &x.isRegularFile) + m.Save(2, &x.seekable) + m.Save(3, &x.haveQueue) + m.Save(4, &x.queue) + m.Save(5, &x.off) +} + +func (x *specialFileFD) afterLoad() {} + +func (x *specialFileFD) StateLoad(m state.Source) { + m.Load(0, &x.fileDescription) + m.Load(1, &x.isRegularFile) + m.Load(2, &x.seekable) + m.Load(3, &x.haveQueue) + m.Load(4, &x.queue) + m.Load(5, &x.off) +} + func init() { state.Register((*dentryList)(nil)) state.Register((*dentryEntry)(nil)) + state.Register((*directoryFD)(nil)) + state.Register((*FilesystemType)(nil)) + state.Register((*filesystem)(nil)) + state.Register((*inodeNumber)(nil)) + state.Register((*filesystemOptions)(nil)) + state.Register((*InteropMode)(nil)) + state.Register((*InternalFilesystemOptions)(nil)) + state.Register((*dentry)(nil)) + state.Register((*fileDescription)(nil)) + state.Register((*regularFileFD)(nil)) + state.Register((*dentryPlatformFile)(nil)) + state.Register((*endpoint)(nil)) + state.Register((*specialFileFD)(nil)) } diff --git a/pkg/sentry/fsimpl/gofer/handle.go b/pkg/sentry/fsimpl/gofer/handle.go index 104157512..a9ebe1206 100644 --- a/pkg/sentry/fsimpl/gofer/handle.go +++ b/pkg/sentry/fsimpl/gofer/handle.go @@ -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 diff --git a/pkg/sentry/fsimpl/gofer/regular_file.go b/pkg/sentry/fsimpl/gofer/regular_file.go index 24f03ee94..eeaf6e444 100644 --- a/pkg/sentry/fsimpl/gofer/regular_file.go +++ b/pkg/sentry/fsimpl/gofer/regular_file.go @@ -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. diff --git a/pkg/sentry/fsimpl/gofer/socket.go b/pkg/sentry/fsimpl/gofer/socket.go index 85d2bee72..326b940a7 100644 --- a/pkg/sentry/fsimpl/gofer/socket.go +++ b/pkg/sentry/fsimpl/gofer/socket.go @@ -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 diff --git a/pkg/sentry/fsimpl/gofer/special_file.go b/pkg/sentry/fsimpl/gofer/special_file.go index 576c57491..71581736c 100644 --- a/pkg/sentry/fsimpl/gofer/special_file.go +++ b/pkg/sentry/fsimpl/gofer/special_file.go @@ -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 } |