diff options
Diffstat (limited to 'pkg/sentry/fsimpl/fuse')
-rw-r--r-- | pkg/sentry/fsimpl/fuse/connection.go | 25 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/fuse/dev.go | 16 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/fuse/fuse_state_autogen.go | 333 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/fuse/fusefs.go | 7 |
4 files changed, 376 insertions, 5 deletions
diff --git a/pkg/sentry/fsimpl/fuse/connection.go b/pkg/sentry/fsimpl/fuse/connection.go index dbc5e1954..8ccda1264 100644 --- a/pkg/sentry/fsimpl/fuse/connection.go +++ b/pkg/sentry/fsimpl/fuse/connection.go @@ -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 diff --git a/pkg/sentry/fsimpl/fuse/dev.go b/pkg/sentry/fsimpl/fuse/dev.go index f690ef5ad..1b86a4b4c 100644 --- a/pkg/sentry/fsimpl/fuse/dev.go +++ b/pkg/sentry/fsimpl/fuse/dev.go @@ -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 { diff --git a/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go b/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go index 6c82dce30..b127b2015 100644 --- a/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go +++ b/pkg/sentry/fsimpl/fuse/fuse_state_autogen.go @@ -6,6 +6,332 @@ import ( "gvisor.dev/gvisor/pkg/state" ) +func (x *connection) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.connection" +} + +func (x *connection) StateFields() []string { + return []string{ + "fd", + "attributeVersion", + "initialized", + "initializedChan", + "connected", + "connInitError", + "connInitSuccess", + "aborted", + "numWaiting", + "asyncNum", + "asyncCongestionThreshold", + "asyncNumMax", + "maxRead", + "maxWrite", + "maxPages", + "minor", + "atomicOTrunc", + "asyncRead", + "writebackCache", + "bigWrites", + "dontMask", + "noOpen", + } +} + +func (x *connection) beforeSave() {} + +func (x *connection) StateSave(m state.Sink) { + x.beforeSave() + var initializedChan bool = x.saveInitializedChan() + m.SaveValue(3, initializedChan) + m.Save(0, &x.fd) + m.Save(1, &x.attributeVersion) + m.Save(2, &x.initialized) + m.Save(4, &x.connected) + m.Save(5, &x.connInitError) + m.Save(6, &x.connInitSuccess) + m.Save(7, &x.aborted) + m.Save(8, &x.numWaiting) + m.Save(9, &x.asyncNum) + m.Save(10, &x.asyncCongestionThreshold) + m.Save(11, &x.asyncNumMax) + m.Save(12, &x.maxRead) + m.Save(13, &x.maxWrite) + m.Save(14, &x.maxPages) + m.Save(15, &x.minor) + m.Save(16, &x.atomicOTrunc) + m.Save(17, &x.asyncRead) + m.Save(18, &x.writebackCache) + m.Save(19, &x.bigWrites) + m.Save(20, &x.dontMask) + m.Save(21, &x.noOpen) +} + +func (x *connection) afterLoad() {} + +func (x *connection) StateLoad(m state.Source) { + m.Load(0, &x.fd) + m.Load(1, &x.attributeVersion) + m.Load(2, &x.initialized) + m.Load(4, &x.connected) + m.Load(5, &x.connInitError) + m.Load(6, &x.connInitSuccess) + m.Load(7, &x.aborted) + m.Load(8, &x.numWaiting) + m.Load(9, &x.asyncNum) + m.Load(10, &x.asyncCongestionThreshold) + m.Load(11, &x.asyncNumMax) + m.Load(12, &x.maxRead) + m.Load(13, &x.maxWrite) + m.Load(14, &x.maxPages) + m.Load(15, &x.minor) + m.Load(16, &x.atomicOTrunc) + m.Load(17, &x.asyncRead) + m.Load(18, &x.writebackCache) + m.Load(19, &x.bigWrites) + m.Load(20, &x.dontMask) + m.Load(21, &x.noOpen) + m.LoadValue(3, new(bool), func(y interface{}) { x.loadInitializedChan(y.(bool)) }) +} + +func (x *fuseDevice) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.fuseDevice" +} + +func (x *fuseDevice) StateFields() []string { + return []string{} +} + +func (x *fuseDevice) beforeSave() {} + +func (x *fuseDevice) StateSave(m state.Sink) { + x.beforeSave() +} + +func (x *fuseDevice) afterLoad() {} + +func (x *fuseDevice) StateLoad(m state.Source) { +} + +func (x *DeviceFD) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.DeviceFD" +} + +func (x *DeviceFD) StateFields() []string { + return []string{ + "vfsfd", + "FileDescriptionDefaultImpl", + "DentryMetadataFileDescriptionImpl", + "NoLockFD", + "nextOpID", + "queue", + "numActiveRequests", + "completions", + "writeCursor", + "writeBuf", + "writeCursorFR", + "waitQueue", + "fullQueueCh", + "fs", + } +} + +func (x *DeviceFD) beforeSave() {} + +func (x *DeviceFD) StateSave(m state.Sink) { + x.beforeSave() + var fullQueueCh int = x.saveFullQueueCh() + m.SaveValue(12, fullQueueCh) + m.Save(0, &x.vfsfd) + m.Save(1, &x.FileDescriptionDefaultImpl) + m.Save(2, &x.DentryMetadataFileDescriptionImpl) + m.Save(3, &x.NoLockFD) + m.Save(4, &x.nextOpID) + m.Save(5, &x.queue) + m.Save(6, &x.numActiveRequests) + m.Save(7, &x.completions) + m.Save(8, &x.writeCursor) + m.Save(9, &x.writeBuf) + m.Save(10, &x.writeCursorFR) + m.Save(11, &x.waitQueue) + m.Save(13, &x.fs) +} + +func (x *DeviceFD) afterLoad() {} + +func (x *DeviceFD) StateLoad(m state.Source) { + m.Load(0, &x.vfsfd) + m.Load(1, &x.FileDescriptionDefaultImpl) + m.Load(2, &x.DentryMetadataFileDescriptionImpl) + m.Load(3, &x.NoLockFD) + m.Load(4, &x.nextOpID) + m.Load(5, &x.queue) + m.Load(6, &x.numActiveRequests) + m.Load(7, &x.completions) + m.Load(8, &x.writeCursor) + m.Load(9, &x.writeBuf) + m.Load(10, &x.writeCursorFR) + m.Load(11, &x.waitQueue) + m.Load(13, &x.fs) + m.LoadValue(12, new(int), func(y interface{}) { x.loadFullQueueCh(y.(int)) }) +} + +func (x *FilesystemType) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.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 *filesystemOptions) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.filesystemOptions" +} + +func (x *filesystemOptions) StateFields() []string { + return []string{ + "userID", + "groupID", + "rootMode", + "maxActiveRequests", + "maxRead", + } +} + +func (x *filesystemOptions) beforeSave() {} + +func (x *filesystemOptions) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.userID) + m.Save(1, &x.groupID) + m.Save(2, &x.rootMode) + m.Save(3, &x.maxActiveRequests) + m.Save(4, &x.maxRead) +} + +func (x *filesystemOptions) afterLoad() {} + +func (x *filesystemOptions) StateLoad(m state.Source) { + m.Load(0, &x.userID) + m.Load(1, &x.groupID) + m.Load(2, &x.rootMode) + m.Load(3, &x.maxActiveRequests) + m.Load(4, &x.maxRead) +} + +func (x *filesystem) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.filesystem" +} + +func (x *filesystem) StateFields() []string { + return []string{ + "Filesystem", + "devMinor", + "conn", + "opts", + "umounted", + } +} + +func (x *filesystem) beforeSave() {} + +func (x *filesystem) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.Filesystem) + m.Save(1, &x.devMinor) + m.Save(2, &x.conn) + m.Save(3, &x.opts) + m.Save(4, &x.umounted) +} + +func (x *filesystem) afterLoad() {} + +func (x *filesystem) StateLoad(m state.Source) { + m.Load(0, &x.Filesystem) + m.Load(1, &x.devMinor) + m.Load(2, &x.conn) + m.Load(3, &x.opts) + m.Load(4, &x.umounted) +} + +func (x *inode) StateTypeName() string { + return "pkg/sentry/fsimpl/fuse.inode" +} + +func (x *inode) StateFields() []string { + return []string{ + "inodeRefs", + "InodeAttrs", + "InodeDirectoryNoNewChildren", + "InodeNoDynamicLookup", + "InodeNotSymlink", + "OrderedChildren", + "dentry", + "fs", + "metadataMu", + "nodeID", + "locks", + "size", + "attributeVersion", + "attributeTime", + "version", + "link", + } +} + +func (x *inode) beforeSave() {} + +func (x *inode) StateSave(m state.Sink) { + x.beforeSave() + m.Save(0, &x.inodeRefs) + m.Save(1, &x.InodeAttrs) + m.Save(2, &x.InodeDirectoryNoNewChildren) + m.Save(3, &x.InodeNoDynamicLookup) + m.Save(4, &x.InodeNotSymlink) + m.Save(5, &x.OrderedChildren) + m.Save(6, &x.dentry) + m.Save(7, &x.fs) + m.Save(8, &x.metadataMu) + m.Save(9, &x.nodeID) + m.Save(10, &x.locks) + m.Save(11, &x.size) + m.Save(12, &x.attributeVersion) + m.Save(13, &x.attributeTime) + m.Save(14, &x.version) + m.Save(15, &x.link) +} + +func (x *inode) afterLoad() {} + +func (x *inode) StateLoad(m state.Source) { + m.Load(0, &x.inodeRefs) + m.Load(1, &x.InodeAttrs) + m.Load(2, &x.InodeDirectoryNoNewChildren) + m.Load(3, &x.InodeNoDynamicLookup) + m.Load(4, &x.InodeNotSymlink) + m.Load(5, &x.OrderedChildren) + m.Load(6, &x.dentry) + m.Load(7, &x.fs) + m.Load(8, &x.metadataMu) + m.Load(9, &x.nodeID) + m.Load(10, &x.locks) + m.Load(11, &x.size) + m.Load(12, &x.attributeVersion) + m.Load(13, &x.attributeTime) + m.Load(14, &x.version) + m.Load(15, &x.link) +} + func (x *inodeRefs) StateTypeName() string { return "pkg/sentry/fsimpl/fuse.inodeRefs" } @@ -187,6 +513,13 @@ func (x *Response) StateLoad(m state.Source) { } func init() { + state.Register((*connection)(nil)) + state.Register((*fuseDevice)(nil)) + state.Register((*DeviceFD)(nil)) + state.Register((*FilesystemType)(nil)) + state.Register((*filesystemOptions)(nil)) + state.Register((*filesystem)(nil)) + state.Register((*inode)(nil)) state.Register((*inodeRefs)(nil)) state.Register((*requestList)(nil)) state.Register((*requestEntry)(nil)) diff --git a/pkg/sentry/fsimpl/fuse/fusefs.go b/pkg/sentry/fsimpl/fuse/fusefs.go index 5ccfc43e7..2f7cd8b8a 100644 --- a/pkg/sentry/fsimpl/fuse/fusefs.go +++ b/pkg/sentry/fsimpl/fuse/fusefs.go @@ -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 |