summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/sentry/devices/memdev/full.go4
-rw-r--r--pkg/sentry/devices/memdev/memdev_state_autogen.go222
-rw-r--r--pkg/sentry/devices/memdev/null.go4
-rw-r--r--pkg/sentry/devices/memdev/random.go4
-rw-r--r--pkg/sentry/devices/memdev/zero.go4
-rw-r--r--pkg/sentry/devices/ttydev/ttydev.go2
-rw-r--r--pkg/sentry/devices/ttydev/ttydev_state_autogen.go27
-rw-r--r--pkg/sentry/fsimpl/devpts/devpts.go8
-rw-r--r--pkg/sentry/fsimpl/devpts/devpts_state_autogen.go289
-rw-r--r--pkg/sentry/fsimpl/devpts/master.go3
-rw-r--r--pkg/sentry/fsimpl/devpts/replica.go3
-rw-r--r--pkg/sentry/fsimpl/devtmpfs/devtmpfs.go4
-rw-r--r--pkg/sentry/fsimpl/devtmpfs/devtmpfs_state_autogen.go37
-rw-r--r--pkg/sentry/fsimpl/eventfd/eventfd.go2
-rw-r--r--pkg/sentry/fsimpl/eventfd/eventfd_state_autogen.go52
-rw-r--r--pkg/sentry/fsimpl/fuse/connection.go25
-rw-r--r--pkg/sentry/fsimpl/fuse/dev.go16
-rw-r--r--pkg/sentry/fsimpl/fuse/fuse_state_autogen.go333
-rw-r--r--pkg/sentry/fsimpl/fuse/fusefs.go7
-rw-r--r--pkg/sentry/fsimpl/gofer/directory.go3
-rw-r--r--pkg/sentry/fsimpl/gofer/gofer.go39
-rw-r--r--pkg/sentry/fsimpl/gofer/gofer_state_autogen.go488
-rw-r--r--pkg/sentry/fsimpl/gofer/handle.go2
-rw-r--r--pkg/sentry/fsimpl/gofer/regular_file.go7
-rw-r--r--pkg/sentry/fsimpl/gofer/socket.go4
-rw-r--r--pkg/sentry/fsimpl/gofer/special_file.go6
-rw-r--r--pkg/sentry/fsimpl/host/host.go12
-rw-r--r--pkg/sentry/fsimpl/host/host_state_autogen.go209
-rw-r--r--pkg/sentry/fsimpl/host/mmap.go6
-rw-r--r--pkg/sentry/fsimpl/host/tty.go2
-rw-r--r--pkg/sentry/fsimpl/kernfs/fd_impl_util.go8
-rw-r--r--pkg/sentry/fsimpl/kernfs/inode_impl_util.go26
-rw-r--r--pkg/sentry/fsimpl/kernfs/kernfs.go10
-rw-r--r--pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go493
-rw-r--r--pkg/sentry/fsimpl/kernfs/symlink.go2
-rw-r--r--pkg/sentry/fsimpl/overlay/directory.go3
-rw-r--r--pkg/sentry/fsimpl/overlay/non_directory.go3
-rw-r--r--pkg/sentry/fsimpl/overlay/overlay.go16
-rw-r--r--pkg/sentry/fsimpl/overlay/overlay_state_autogen.go282
-rw-r--r--pkg/sentry/fsimpl/pipefs/pipefs.go4
-rw-r--r--pkg/sentry/fsimpl/pipefs/pipefs_state_autogen.go102
-rw-r--r--pkg/sentry/fsimpl/proc/filesystem.go7
-rw-r--r--pkg/sentry/fsimpl/proc/proc_state_autogen.go494
-rw-r--r--pkg/sentry/fsimpl/proc/subtasks.go1
-rw-r--r--pkg/sentry/fsimpl/proc/task.go2
-rw-r--r--pkg/sentry/fsimpl/proc/task_fds.go1
-rw-r--r--pkg/sentry/fsimpl/proc/task_files.go5
-rw-r--r--pkg/sentry/fsimpl/proc/task_net.go1
-rw-r--r--pkg/sentry/fsimpl/proc/tasks.go2
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_files.go6
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_sys.go1
-rw-r--r--pkg/sentry/fsimpl/signalfd/signalfd.go4
-rw-r--r--pkg/sentry/fsimpl/signalfd/signalfd_state_autogen.go46
-rw-r--r--pkg/sentry/fsimpl/sockfs/sockfs.go5
-rw-r--r--pkg/sentry/fsimpl/sockfs/sockfs_state_autogen.go87
-rw-r--r--pkg/sentry/fsimpl/sys/kcov.go3
-rw-r--r--pkg/sentry/fsimpl/sys/sys.go9
-rw-r--r--pkg/sentry/fsimpl/sys/sys_state_autogen.go214
-rw-r--r--pkg/sentry/fsimpl/timerfd/timerfd.go2
-rw-r--r--pkg/sentry/fsimpl/timerfd/timerfd_state_autogen.go49
-rw-r--r--pkg/sentry/fsimpl/tmpfs/device_file.go1
-rw-r--r--pkg/sentry/fsimpl/tmpfs/directory.go4
-rw-r--r--pkg/sentry/fsimpl/tmpfs/named_pipe.go1
-rw-r--r--pkg/sentry/fsimpl/tmpfs/regular_file.go7
-rw-r--r--pkg/sentry/fsimpl/tmpfs/socket_file.go2
-rw-r--r--pkg/sentry/fsimpl/tmpfs/symlink.go1
-rw-r--r--pkg/sentry/fsimpl/tmpfs/tmpfs.go26
-rw-r--r--pkg/sentry/fsimpl/tmpfs/tmpfs_state_autogen.go470
-rw-r--r--pkg/sentry/kernel/kernel.go13
-rw-r--r--pkg/sentry/socket/unix/unix_state_autogen.go36
-rw-r--r--pkg/sentry/socket/unix/unix_vfs2.go2
-rw-r--r--pkg/sentry/state/state.go6
-rw-r--r--pkg/sentry/vfs/anonfs.go5
-rw-r--r--pkg/sentry/vfs/dentry.go2
-rw-r--r--pkg/sentry/vfs/device.go3
-rw-r--r--pkg/sentry/vfs/epoll.go9
-rw-r--r--pkg/sentry/vfs/file_description.go10
-rw-r--r--pkg/sentry/vfs/file_description_impl_util.go28
-rw-r--r--pkg/sentry/vfs/filesystem.go6
-rw-r--r--pkg/sentry/vfs/filesystem_type.go2
-rw-r--r--pkg/sentry/vfs/inotify.go2
-rw-r--r--pkg/sentry/vfs/lock.go2
-rw-r--r--pkg/sentry/vfs/mount.go9
-rw-r--r--pkg/sentry/vfs/mount_unsafe.go11
-rw-r--r--pkg/sentry/vfs/options.go30
-rw-r--r--pkg/sentry/vfs/permissions.go2
-rw-r--r--pkg/sentry/vfs/resolving_path.go5
-rw-r--r--pkg/sentry/vfs/vfs.go2
-rw-r--r--pkg/sentry/vfs/vfs_state_autogen.go1252
-rw-r--r--pkg/state/types.go14
90 files changed, 5604 insertions, 71 deletions
diff --git a/pkg/sentry/devices/memdev/full.go b/pkg/sentry/devices/memdev/full.go
index 511179e31..fece3e762 100644
--- a/pkg/sentry/devices/memdev/full.go
+++ b/pkg/sentry/devices/memdev/full.go
@@ -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
diff --git a/pkg/sentry/devices/memdev/memdev_state_autogen.go b/pkg/sentry/devices/memdev/memdev_state_autogen.go
index 2676fbbe5..127ea03ee 100644
--- a/pkg/sentry/devices/memdev/memdev_state_autogen.go
+++ b/pkg/sentry/devices/memdev/memdev_state_autogen.go
@@ -1,3 +1,225 @@
// automatically generated by stateify.
package memdev
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *fullDevice) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.fullDevice"
+}
+
+func (x *fullDevice) StateFields() []string {
+ return []string{}
+}
+
+func (x *fullDevice) beforeSave() {}
+
+func (x *fullDevice) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *fullDevice) afterLoad() {}
+
+func (x *fullDevice) StateLoad(m state.Source) {
+}
+
+func (x *fullFD) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.fullFD"
+}
+
+func (x *fullFD) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ }
+}
+
+func (x *fullFD) beforeSave() {}
+
+func (x *fullFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+}
+
+func (x *fullFD) afterLoad() {}
+
+func (x *fullFD) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Load(3, &x.NoLockFD)
+}
+
+func (x *nullDevice) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.nullDevice"
+}
+
+func (x *nullDevice) StateFields() []string {
+ return []string{}
+}
+
+func (x *nullDevice) beforeSave() {}
+
+func (x *nullDevice) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *nullDevice) afterLoad() {}
+
+func (x *nullDevice) StateLoad(m state.Source) {
+}
+
+func (x *nullFD) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.nullFD"
+}
+
+func (x *nullFD) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ }
+}
+
+func (x *nullFD) beforeSave() {}
+
+func (x *nullFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+}
+
+func (x *nullFD) afterLoad() {}
+
+func (x *nullFD) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Load(3, &x.NoLockFD)
+}
+
+func (x *randomDevice) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.randomDevice"
+}
+
+func (x *randomDevice) StateFields() []string {
+ return []string{}
+}
+
+func (x *randomDevice) beforeSave() {}
+
+func (x *randomDevice) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *randomDevice) afterLoad() {}
+
+func (x *randomDevice) StateLoad(m state.Source) {
+}
+
+func (x *randomFD) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.randomFD"
+}
+
+func (x *randomFD) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ "off",
+ }
+}
+
+func (x *randomFD) beforeSave() {}
+
+func (x *randomFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+ m.Save(4, &x.off)
+}
+
+func (x *randomFD) afterLoad() {}
+
+func (x *randomFD) 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.off)
+}
+
+func (x *zeroDevice) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.zeroDevice"
+}
+
+func (x *zeroDevice) StateFields() []string {
+ return []string{}
+}
+
+func (x *zeroDevice) beforeSave() {}
+
+func (x *zeroDevice) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *zeroDevice) afterLoad() {}
+
+func (x *zeroDevice) StateLoad(m state.Source) {
+}
+
+func (x *zeroFD) StateTypeName() string {
+ return "pkg/sentry/devices/memdev.zeroFD"
+}
+
+func (x *zeroFD) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ }
+}
+
+func (x *zeroFD) beforeSave() {}
+
+func (x *zeroFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+}
+
+func (x *zeroFD) afterLoad() {}
+
+func (x *zeroFD) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Load(3, &x.NoLockFD)
+}
+
+func init() {
+ state.Register((*fullDevice)(nil))
+ state.Register((*fullFD)(nil))
+ state.Register((*nullDevice)(nil))
+ state.Register((*nullFD)(nil))
+ state.Register((*randomDevice)(nil))
+ state.Register((*randomFD)(nil))
+ state.Register((*zeroDevice)(nil))
+ state.Register((*zeroFD)(nil))
+}
diff --git a/pkg/sentry/devices/memdev/null.go b/pkg/sentry/devices/memdev/null.go
index 4918dbeeb..ff5837747 100644
--- a/pkg/sentry/devices/memdev/null.go
+++ b/pkg/sentry/devices/memdev/null.go
@@ -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
diff --git a/pkg/sentry/devices/memdev/random.go b/pkg/sentry/devices/memdev/random.go
index 5e7fe0280..ac943e3ba 100644
--- a/pkg/sentry/devices/memdev/random.go
+++ b/pkg/sentry/devices/memdev/random.go
@@ -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
diff --git a/pkg/sentry/devices/memdev/zero.go b/pkg/sentry/devices/memdev/zero.go
index 60cfea888..1929e41cd 100644
--- a/pkg/sentry/devices/memdev/zero.go
+++ b/pkg/sentry/devices/memdev/zero.go
@@ -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
diff --git a/pkg/sentry/devices/ttydev/ttydev.go b/pkg/sentry/devices/ttydev/ttydev.go
index 664e54498..a287c65ca 100644
--- a/pkg/sentry/devices/ttydev/ttydev.go
+++ b/pkg/sentry/devices/ttydev/ttydev.go
@@ -30,6 +30,8 @@ const (
)
// ttyDevice implements vfs.Device for /dev/tty.
+//
+// +stateify savable
type ttyDevice struct{}
// Open implements vfs.Device.Open.
diff --git a/pkg/sentry/devices/ttydev/ttydev_state_autogen.go b/pkg/sentry/devices/ttydev/ttydev_state_autogen.go
index 29014107c..9883dcf08 100644
--- a/pkg/sentry/devices/ttydev/ttydev_state_autogen.go
+++ b/pkg/sentry/devices/ttydev/ttydev_state_autogen.go
@@ -1,3 +1,30 @@
// automatically generated by stateify.
package ttydev
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *ttyDevice) StateTypeName() string {
+ return "pkg/sentry/devices/ttydev.ttyDevice"
+}
+
+func (x *ttyDevice) StateFields() []string {
+ return []string{}
+}
+
+func (x *ttyDevice) beforeSave() {}
+
+func (x *ttyDevice) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *ttyDevice) afterLoad() {}
+
+func (x *ttyDevice) StateLoad(m state.Source) {
+}
+
+func init() {
+ state.Register((*ttyDevice)(nil))
+}
diff --git a/pkg/sentry/fsimpl/devpts/devpts.go b/pkg/sentry/fsimpl/devpts/devpts.go
index 77d1f493d..903135fae 100644
--- a/pkg/sentry/fsimpl/devpts/devpts.go
+++ b/pkg/sentry/fsimpl/devpts/devpts.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/devpts/devpts_state_autogen.go b/pkg/sentry/fsimpl/devpts/devpts_state_autogen.go
index 5e9f200c8..61e4f6fdf 100644
--- a/pkg/sentry/fsimpl/devpts/devpts_state_autogen.go
+++ b/pkg/sentry/fsimpl/devpts/devpts_state_autogen.go
@@ -6,6 +6,129 @@ import (
"gvisor.dev/gvisor/pkg/state"
)
+func (x *FilesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.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/devpts.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *rootInode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.rootInode"
+}
+
+func (x *rootInode) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "AlwaysValid",
+ "InodeAttrs",
+ "InodeDirectoryNoNewChildren",
+ "InodeNotSymlink",
+ "OrderedChildren",
+ "rootInodeRefs",
+ "locks",
+ "dentry",
+ "master",
+ "root",
+ "replicas",
+ "nextIdx",
+ }
+}
+
+func (x *rootInode) beforeSave() {}
+
+func (x *rootInode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.AlwaysValid)
+ m.Save(2, &x.InodeAttrs)
+ m.Save(3, &x.InodeDirectoryNoNewChildren)
+ m.Save(4, &x.InodeNotSymlink)
+ m.Save(5, &x.OrderedChildren)
+ m.Save(6, &x.rootInodeRefs)
+ m.Save(7, &x.locks)
+ m.Save(8, &x.dentry)
+ m.Save(9, &x.master)
+ m.Save(10, &x.root)
+ m.Save(11, &x.replicas)
+ m.Save(12, &x.nextIdx)
+}
+
+func (x *rootInode) afterLoad() {}
+
+func (x *rootInode) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.AlwaysValid)
+ m.Load(2, &x.InodeAttrs)
+ m.Load(3, &x.InodeDirectoryNoNewChildren)
+ m.Load(4, &x.InodeNotSymlink)
+ m.Load(5, &x.OrderedChildren)
+ m.Load(6, &x.rootInodeRefs)
+ m.Load(7, &x.locks)
+ m.Load(8, &x.dentry)
+ m.Load(9, &x.master)
+ m.Load(10, &x.root)
+ m.Load(11, &x.replicas)
+ m.Load(12, &x.nextIdx)
+}
+
+func (x *implStatFS) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.implStatFS"
+}
+
+func (x *implStatFS) StateFields() []string {
+ return []string{}
+}
+
+func (x *implStatFS) beforeSave() {}
+
+func (x *implStatFS) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *implStatFS) afterLoad() {}
+
+func (x *implStatFS) StateLoad(m state.Source) {
+}
+
func (x *lineDiscipline) StateTypeName() string {
return "pkg/sentry/fsimpl/devpts.lineDiscipline"
}
@@ -85,6 +208,85 @@ func (x *inputQueueTransformer) afterLoad() {}
func (x *inputQueueTransformer) StateLoad(m state.Source) {
}
+func (x *masterInode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.masterInode"
+}
+
+func (x *masterInode) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ "locks",
+ "dentry",
+ "root",
+ }
+}
+
+func (x *masterInode) beforeSave() {}
+
+func (x *masterInode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeNoopRefCount)
+ m.Save(3, &x.InodeNotDirectory)
+ m.Save(4, &x.InodeNotSymlink)
+ m.Save(5, &x.locks)
+ m.Save(6, &x.dentry)
+ m.Save(7, &x.root)
+}
+
+func (x *masterInode) afterLoad() {}
+
+func (x *masterInode) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeNoopRefCount)
+ m.Load(3, &x.InodeNotDirectory)
+ m.Load(4, &x.InodeNotSymlink)
+ m.Load(5, &x.locks)
+ m.Load(6, &x.dentry)
+ m.Load(7, &x.root)
+}
+
+func (x *masterFileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.masterFileDescription"
+}
+
+func (x *masterFileDescription) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "LockFD",
+ "inode",
+ "t",
+ }
+}
+
+func (x *masterFileDescription) beforeSave() {}
+
+func (x *masterFileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.LockFD)
+ m.Save(3, &x.inode)
+ m.Save(4, &x.t)
+}
+
+func (x *masterFileDescription) afterLoad() {}
+
+func (x *masterFileDescription) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.LockFD)
+ m.Load(3, &x.inode)
+ m.Load(4, &x.t)
+}
+
func (x *queue) StateTypeName() string {
return "pkg/sentry/fsimpl/devpts.queue"
}
@@ -120,6 +322,85 @@ func (x *queue) StateLoad(m state.Source) {
m.Load(4, &x.transformer)
}
+func (x *replicaInode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.replicaInode"
+}
+
+func (x *replicaInode) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ "locks",
+ "dentry",
+ "root",
+ "t",
+ }
+}
+
+func (x *replicaInode) beforeSave() {}
+
+func (x *replicaInode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeNoopRefCount)
+ m.Save(3, &x.InodeNotDirectory)
+ m.Save(4, &x.InodeNotSymlink)
+ m.Save(5, &x.locks)
+ m.Save(6, &x.dentry)
+ m.Save(7, &x.root)
+ m.Save(8, &x.t)
+}
+
+func (x *replicaInode) afterLoad() {}
+
+func (x *replicaInode) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeNoopRefCount)
+ m.Load(3, &x.InodeNotDirectory)
+ m.Load(4, &x.InodeNotSymlink)
+ m.Load(5, &x.locks)
+ m.Load(6, &x.dentry)
+ m.Load(7, &x.root)
+ m.Load(8, &x.t)
+}
+
+func (x *replicaFileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devpts.replicaFileDescription"
+}
+
+func (x *replicaFileDescription) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "LockFD",
+ "inode",
+ }
+}
+
+func (x *replicaFileDescription) beforeSave() {}
+
+func (x *replicaFileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.LockFD)
+ m.Save(3, &x.inode)
+}
+
+func (x *replicaFileDescription) afterLoad() {}
+
+func (x *replicaFileDescription) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.LockFD)
+ m.Load(3, &x.inode)
+}
+
func (x *rootInodeRefs) StateTypeName() string {
return "pkg/sentry/fsimpl/devpts.rootInodeRefs"
}
@@ -176,10 +457,18 @@ func (x *Terminal) StateLoad(m state.Source) {
}
func init() {
+ state.Register((*FilesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*rootInode)(nil))
+ state.Register((*implStatFS)(nil))
state.Register((*lineDiscipline)(nil))
state.Register((*outputQueueTransformer)(nil))
state.Register((*inputQueueTransformer)(nil))
+ state.Register((*masterInode)(nil))
+ state.Register((*masterFileDescription)(nil))
state.Register((*queue)(nil))
+ state.Register((*replicaInode)(nil))
+ state.Register((*replicaFileDescription)(nil))
state.Register((*rootInodeRefs)(nil))
state.Register((*Terminal)(nil))
}
diff --git a/pkg/sentry/fsimpl/devpts/master.go b/pkg/sentry/fsimpl/devpts/master.go
index 98d4ffb22..bfcaf60bd 100644
--- a/pkg/sentry/fsimpl/devpts/master.go
+++ b/pkg/sentry/fsimpl/devpts/master.go
@@ -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
diff --git a/pkg/sentry/fsimpl/devpts/replica.go b/pkg/sentry/fsimpl/devpts/replica.go
index 816bac80c..9638eb6c5 100644
--- a/pkg/sentry/fsimpl/devpts/replica.go
+++ b/pkg/sentry/fsimpl/devpts/replica.go
@@ -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
diff --git a/pkg/sentry/fsimpl/devtmpfs/devtmpfs.go b/pkg/sentry/fsimpl/devtmpfs/devtmpfs.go
index a23094e54..6d1753080 100644
--- a/pkg/sentry/fsimpl/devtmpfs/devtmpfs.go
+++ b/pkg/sentry/fsimpl/devtmpfs/devtmpfs.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/devtmpfs/devtmpfs_state_autogen.go b/pkg/sentry/fsimpl/devtmpfs/devtmpfs_state_autogen.go
index ac054eb77..1253bed4e 100644
--- a/pkg/sentry/fsimpl/devtmpfs/devtmpfs_state_autogen.go
+++ b/pkg/sentry/fsimpl/devtmpfs/devtmpfs_state_autogen.go
@@ -1,3 +1,40 @@
// automatically generated by stateify.
package devtmpfs
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *FilesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/devtmpfs.FilesystemType"
+}
+
+func (x *FilesystemType) StateFields() []string {
+ return []string{
+ "initErr",
+ "fs",
+ "root",
+ }
+}
+
+func (x *FilesystemType) beforeSave() {}
+
+func (x *FilesystemType) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.initErr)
+ m.Save(1, &x.fs)
+ m.Save(2, &x.root)
+}
+
+func (x *FilesystemType) afterLoad() {}
+
+func (x *FilesystemType) StateLoad(m state.Source) {
+ m.Load(0, &x.initErr)
+ m.Load(1, &x.fs)
+ m.Load(2, &x.root)
+}
+
+func init() {
+ state.Register((*FilesystemType)(nil))
+}
diff --git a/pkg/sentry/fsimpl/eventfd/eventfd.go b/pkg/sentry/fsimpl/eventfd/eventfd.go
index bb0bf3a07..1c27ad700 100644
--- a/pkg/sentry/fsimpl/eventfd/eventfd.go
+++ b/pkg/sentry/fsimpl/eventfd/eventfd.go
@@ -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
diff --git a/pkg/sentry/fsimpl/eventfd/eventfd_state_autogen.go b/pkg/sentry/fsimpl/eventfd/eventfd_state_autogen.go
index e83f6aed8..0507be064 100644
--- a/pkg/sentry/fsimpl/eventfd/eventfd_state_autogen.go
+++ b/pkg/sentry/fsimpl/eventfd/eventfd_state_autogen.go
@@ -1,3 +1,55 @@
// automatically generated by stateify.
package eventfd
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *EventFileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/eventfd.EventFileDescription"
+}
+
+func (x *EventFileDescription) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ "val",
+ "semMode",
+ "hostfd",
+ }
+}
+
+func (x *EventFileDescription) beforeSave() {}
+
+func (x *EventFileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ if !state.IsZeroValue(&x.queue) {
+ state.Failf("queue is %#v, expected zero", &x.queue)
+ }
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+ m.Save(4, &x.val)
+ m.Save(5, &x.semMode)
+ m.Save(6, &x.hostfd)
+}
+
+func (x *EventFileDescription) afterLoad() {}
+
+func (x *EventFileDescription) 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.val)
+ m.Load(5, &x.semMode)
+ m.Load(6, &x.hostfd)
+}
+
+func init() {
+ state.Register((*EventFileDescription)(nil))
+}
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
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
}
diff --git a/pkg/sentry/fsimpl/host/host.go b/pkg/sentry/fsimpl/host/host.go
index c0cef3453..ffe4ddb32 100644
--- a/pkg/sentry/fsimpl/host/host.go
+++ b/pkg/sentry/fsimpl/host/host.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/host/host_state_autogen.go b/pkg/sentry/fsimpl/host/host_state_autogen.go
index 400320c78..c97fa7212 100644
--- a/pkg/sentry/fsimpl/host/host_state_autogen.go
+++ b/pkg/sentry/fsimpl/host/host_state_autogen.go
@@ -29,6 +29,148 @@ func (x *ConnectedEndpointRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *filesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/host.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/host.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *inode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/host.inode"
+}
+
+func (x *inode) StateFields() []string {
+ return []string{
+ "InodeNoStatFS",
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ "locks",
+ "inodeRefs",
+ "hostFD",
+ "ino",
+ "isTTY",
+ "seekable",
+ "wouldBlock",
+ "queue",
+ "canMap",
+ "mappings",
+ "pf",
+ }
+}
+
+func (x *inode) beforeSave() {}
+
+func (x *inode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.InodeNoStatFS)
+ m.Save(1, &x.InodeNotDirectory)
+ m.Save(2, &x.InodeNotSymlink)
+ m.Save(3, &x.locks)
+ m.Save(4, &x.inodeRefs)
+ m.Save(5, &x.hostFD)
+ m.Save(6, &x.ino)
+ m.Save(7, &x.isTTY)
+ m.Save(8, &x.seekable)
+ m.Save(9, &x.wouldBlock)
+ m.Save(10, &x.queue)
+ m.Save(11, &x.canMap)
+ m.Save(12, &x.mappings)
+ m.Save(13, &x.pf)
+}
+
+func (x *inode) afterLoad() {}
+
+func (x *inode) StateLoad(m state.Source) {
+ m.Load(0, &x.InodeNoStatFS)
+ m.Load(1, &x.InodeNotDirectory)
+ m.Load(2, &x.InodeNotSymlink)
+ m.Load(3, &x.locks)
+ m.Load(4, &x.inodeRefs)
+ m.Load(5, &x.hostFD)
+ m.Load(6, &x.ino)
+ m.Load(7, &x.isTTY)
+ m.Load(8, &x.seekable)
+ m.Load(9, &x.wouldBlock)
+ m.Load(10, &x.queue)
+ m.Load(11, &x.canMap)
+ m.Load(12, &x.mappings)
+ m.Load(13, &x.pf)
+}
+
+func (x *fileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/host.fileDescription"
+}
+
+func (x *fileDescription) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "LockFD",
+ "inode",
+ "offset",
+ }
+}
+
+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)
+ m.Save(3, &x.inode)
+ m.Save(4, &x.offset)
+}
+
+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)
+ m.Load(3, &x.inode)
+ m.Load(4, &x.offset)
+}
+
func (x *inodeRefs) StateTypeName() string {
return "pkg/sentry/fsimpl/host.inodeRefs"
}
@@ -52,6 +194,35 @@ func (x *inodeRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *inodePlatformFile) StateTypeName() string {
+ return "pkg/sentry/fsimpl/host.inodePlatformFile"
+}
+
+func (x *inodePlatformFile) StateFields() []string {
+ return []string{
+ "inode",
+ "fdRefs",
+ "fileMapper",
+ }
+}
+
+func (x *inodePlatformFile) beforeSave() {}
+
+func (x *inodePlatformFile) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inode)
+ m.Save(1, &x.fdRefs)
+ m.Save(2, &x.fileMapper)
+}
+
+func (x *inodePlatformFile) afterLoad() {}
+
+func (x *inodePlatformFile) StateLoad(m state.Source) {
+ m.Load(0, &x.inode)
+ m.Load(1, &x.fdRefs)
+ m.Load(2, &x.fileMapper)
+}
+
func (x *ConnectedEndpoint) StateTypeName() string {
return "pkg/sentry/fsimpl/host.ConnectedEndpoint"
}
@@ -84,8 +255,46 @@ func (x *ConnectedEndpoint) StateLoad(m state.Source) {
m.Load(3, &x.stype)
}
+func (x *TTYFileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/host.TTYFileDescription"
+}
+
+func (x *TTYFileDescription) StateFields() []string {
+ return []string{
+ "fileDescription",
+ "session",
+ "fgProcessGroup",
+ "termios",
+ }
+}
+
+func (x *TTYFileDescription) beforeSave() {}
+
+func (x *TTYFileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.fileDescription)
+ m.Save(1, &x.session)
+ m.Save(2, &x.fgProcessGroup)
+ m.Save(3, &x.termios)
+}
+
+func (x *TTYFileDescription) afterLoad() {}
+
+func (x *TTYFileDescription) StateLoad(m state.Source) {
+ m.Load(0, &x.fileDescription)
+ m.Load(1, &x.session)
+ m.Load(2, &x.fgProcessGroup)
+ m.Load(3, &x.termios)
+}
+
func init() {
state.Register((*ConnectedEndpointRefs)(nil))
+ state.Register((*filesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*inode)(nil))
+ state.Register((*fileDescription)(nil))
state.Register((*inodeRefs)(nil))
+ state.Register((*inodePlatformFile)(nil))
state.Register((*ConnectedEndpoint)(nil))
+ state.Register((*TTYFileDescription)(nil))
}
diff --git a/pkg/sentry/fsimpl/host/mmap.go b/pkg/sentry/fsimpl/host/mmap.go
index 65d3af38c..b51a17bed 100644
--- a/pkg/sentry/fsimpl/host/mmap.go
+++ b/pkg/sentry/fsimpl/host/mmap.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/host/tty.go b/pkg/sentry/fsimpl/host/tty.go
index e02b9b8f6..f5c596fec 100644
--- a/pkg/sentry/fsimpl/host/tty.go
+++ b/pkg/sentry/fsimpl/host/tty.go
@@ -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
diff --git a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
index 2b4294228..c7bd3baae 100644
--- a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
+++ b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
@@ -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
diff --git a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
index 5cc196980..d8e321acb 100644
--- a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
+++ b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/kernfs/kernfs.go b/pkg/sentry/fsimpl/kernfs/kernfs.go
index 14bf43ede..96dfb03c7 100644
--- a/pkg/sentry/fsimpl/kernfs/kernfs.go
+++ b/pkg/sentry/fsimpl/kernfs/kernfs.go
@@ -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
diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go b/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go
index 31cf0f33c..f42662d2d 100644
--- a/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go
+++ b/pkg/sentry/fsimpl/kernfs/kernfs_state_autogen.go
@@ -105,6 +105,337 @@ func (x *DynamicBytesFD) StateLoad(m state.Source) {
m.Load(4, &x.inode)
}
+func (x *SeekEndConfig) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.SeekEndConfig"
+}
+
+func (x *SeekEndConfig) StateFields() []string {
+ return nil
+}
+
+func (x *GenericDirectoryFDOptions) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.GenericDirectoryFDOptions"
+}
+
+func (x *GenericDirectoryFDOptions) StateFields() []string {
+ return []string{
+ "SeekEnd",
+ }
+}
+
+func (x *GenericDirectoryFDOptions) beforeSave() {}
+
+func (x *GenericDirectoryFDOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.SeekEnd)
+}
+
+func (x *GenericDirectoryFDOptions) afterLoad() {}
+
+func (x *GenericDirectoryFDOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.SeekEnd)
+}
+
+func (x *GenericDirectoryFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.GenericDirectoryFD"
+}
+
+func (x *GenericDirectoryFD) StateFields() []string {
+ return []string{
+ "FileDescriptionDefaultImpl",
+ "DirectoryFileDescriptionDefaultImpl",
+ "LockFD",
+ "seekEnd",
+ "vfsfd",
+ "children",
+ "off",
+ }
+}
+
+func (x *GenericDirectoryFD) beforeSave() {}
+
+func (x *GenericDirectoryFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.FileDescriptionDefaultImpl)
+ m.Save(1, &x.DirectoryFileDescriptionDefaultImpl)
+ m.Save(2, &x.LockFD)
+ m.Save(3, &x.seekEnd)
+ m.Save(4, &x.vfsfd)
+ m.Save(5, &x.children)
+ m.Save(6, &x.off)
+}
+
+func (x *GenericDirectoryFD) afterLoad() {}
+
+func (x *GenericDirectoryFD) StateLoad(m state.Source) {
+ m.Load(0, &x.FileDescriptionDefaultImpl)
+ m.Load(1, &x.DirectoryFileDescriptionDefaultImpl)
+ m.Load(2, &x.LockFD)
+ m.Load(3, &x.seekEnd)
+ m.Load(4, &x.vfsfd)
+ m.Load(5, &x.children)
+ m.Load(6, &x.off)
+}
+
+func (x *InodeNoopRefCount) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeNoopRefCount"
+}
+
+func (x *InodeNoopRefCount) StateFields() []string {
+ return []string{}
+}
+
+func (x *InodeNoopRefCount) beforeSave() {}
+
+func (x *InodeNoopRefCount) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *InodeNoopRefCount) afterLoad() {}
+
+func (x *InodeNoopRefCount) StateLoad(m state.Source) {
+}
+
+func (x *InodeDirectoryNoNewChildren) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeDirectoryNoNewChildren"
+}
+
+func (x *InodeDirectoryNoNewChildren) StateFields() []string {
+ return []string{}
+}
+
+func (x *InodeDirectoryNoNewChildren) beforeSave() {}
+
+func (x *InodeDirectoryNoNewChildren) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *InodeDirectoryNoNewChildren) afterLoad() {}
+
+func (x *InodeDirectoryNoNewChildren) StateLoad(m state.Source) {
+}
+
+func (x *InodeNotDirectory) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeNotDirectory"
+}
+
+func (x *InodeNotDirectory) StateFields() []string {
+ return []string{}
+}
+
+func (x *InodeNotDirectory) beforeSave() {}
+
+func (x *InodeNotDirectory) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *InodeNotDirectory) afterLoad() {}
+
+func (x *InodeNotDirectory) StateLoad(m state.Source) {
+}
+
+func (x *InodeNoDynamicLookup) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeNoDynamicLookup"
+}
+
+func (x *InodeNoDynamicLookup) StateFields() []string {
+ return []string{}
+}
+
+func (x *InodeNoDynamicLookup) beforeSave() {}
+
+func (x *InodeNoDynamicLookup) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *InodeNoDynamicLookup) afterLoad() {}
+
+func (x *InodeNoDynamicLookup) StateLoad(m state.Source) {
+}
+
+func (x *InodeNotSymlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeNotSymlink"
+}
+
+func (x *InodeNotSymlink) StateFields() []string {
+ return []string{}
+}
+
+func (x *InodeNotSymlink) beforeSave() {}
+
+func (x *InodeNotSymlink) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *InodeNotSymlink) afterLoad() {}
+
+func (x *InodeNotSymlink) StateLoad(m state.Source) {
+}
+
+func (x *InodeAttrs) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeAttrs"
+}
+
+func (x *InodeAttrs) StateFields() []string {
+ return []string{
+ "devMajor",
+ "devMinor",
+ "ino",
+ "mode",
+ "uid",
+ "gid",
+ "nlink",
+ }
+}
+
+func (x *InodeAttrs) beforeSave() {}
+
+func (x *InodeAttrs) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.devMajor)
+ m.Save(1, &x.devMinor)
+ m.Save(2, &x.ino)
+ m.Save(3, &x.mode)
+ m.Save(4, &x.uid)
+ m.Save(5, &x.gid)
+ m.Save(6, &x.nlink)
+}
+
+func (x *InodeAttrs) afterLoad() {}
+
+func (x *InodeAttrs) StateLoad(m state.Source) {
+ m.Load(0, &x.devMajor)
+ m.Load(1, &x.devMinor)
+ m.Load(2, &x.ino)
+ m.Load(3, &x.mode)
+ m.Load(4, &x.uid)
+ m.Load(5, &x.gid)
+ m.Load(6, &x.nlink)
+}
+
+func (x *slot) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.slot"
+}
+
+func (x *slot) StateFields() []string {
+ return []string{
+ "Name",
+ "Dentry",
+ "slotEntry",
+ }
+}
+
+func (x *slot) beforeSave() {}
+
+func (x *slot) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Name)
+ m.Save(1, &x.Dentry)
+ m.Save(2, &x.slotEntry)
+}
+
+func (x *slot) afterLoad() {}
+
+func (x *slot) StateLoad(m state.Source) {
+ m.Load(0, &x.Name)
+ m.Load(1, &x.Dentry)
+ m.Load(2, &x.slotEntry)
+}
+
+func (x *OrderedChildrenOptions) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.OrderedChildrenOptions"
+}
+
+func (x *OrderedChildrenOptions) StateFields() []string {
+ return []string{
+ "Writable",
+ }
+}
+
+func (x *OrderedChildrenOptions) beforeSave() {}
+
+func (x *OrderedChildrenOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Writable)
+}
+
+func (x *OrderedChildrenOptions) afterLoad() {}
+
+func (x *OrderedChildrenOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Writable)
+}
+
+func (x *OrderedChildren) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.OrderedChildren"
+}
+
+func (x *OrderedChildren) StateFields() []string {
+ return []string{
+ "writable",
+ "order",
+ "set",
+ }
+}
+
+func (x *OrderedChildren) beforeSave() {}
+
+func (x *OrderedChildren) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.writable)
+ m.Save(1, &x.order)
+ m.Save(2, &x.set)
+}
+
+func (x *OrderedChildren) afterLoad() {}
+
+func (x *OrderedChildren) StateLoad(m state.Source) {
+ m.Load(0, &x.writable)
+ m.Load(1, &x.order)
+ m.Load(2, &x.set)
+}
+
+func (x *renameAcrossDifferentImplementationsError) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.renameAcrossDifferentImplementationsError"
+}
+
+func (x *renameAcrossDifferentImplementationsError) StateFields() []string {
+ return []string{}
+}
+
+func (x *renameAcrossDifferentImplementationsError) beforeSave() {}
+
+func (x *renameAcrossDifferentImplementationsError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *renameAcrossDifferentImplementationsError) afterLoad() {}
+
+func (x *renameAcrossDifferentImplementationsError) StateLoad(m state.Source) {
+}
+
+func (x *InodeSymlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeSymlink"
+}
+
+func (x *InodeSymlink) StateFields() []string {
+ return []string{
+ "InodeNotDirectory",
+ }
+}
+
+func (x *InodeSymlink) beforeSave() {}
+
+func (x *InodeSymlink) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.InodeNotDirectory)
+}
+
+func (x *InodeSymlink) afterLoad() {}
+
+func (x *InodeSymlink) StateLoad(m state.Source) {
+ m.Load(0, &x.InodeNotDirectory)
+}
+
func (x *StaticDirectory) StateTypeName() string {
return "pkg/sentry/fsimpl/kernfs.StaticDirectory"
}
@@ -152,6 +483,114 @@ func (x *StaticDirectory) StateLoad(m state.Source) {
m.Load(8, &x.fdOpts)
}
+func (x *AlwaysValid) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.AlwaysValid"
+}
+
+func (x *AlwaysValid) StateFields() []string {
+ return []string{}
+}
+
+func (x *AlwaysValid) beforeSave() {}
+
+func (x *AlwaysValid) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *AlwaysValid) afterLoad() {}
+
+func (x *AlwaysValid) StateLoad(m state.Source) {
+}
+
+func (x *InodeNoStatFS) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.InodeNoStatFS"
+}
+
+func (x *InodeNoStatFS) StateFields() []string {
+ return []string{}
+}
+
+func (x *InodeNoStatFS) beforeSave() {}
+
+func (x *InodeNoStatFS) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *InodeNoStatFS) afterLoad() {}
+
+func (x *InodeNoStatFS) StateLoad(m state.Source) {
+}
+
+func (x *Filesystem) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.Filesystem"
+}
+
+func (x *Filesystem) StateFields() []string {
+ return []string{
+ "vfsfs",
+ "droppedDentries",
+ "nextInoMinusOne",
+ }
+}
+
+func (x *Filesystem) beforeSave() {}
+
+func (x *Filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfs)
+ m.Save(1, &x.droppedDentries)
+ m.Save(2, &x.nextInoMinusOne)
+}
+
+func (x *Filesystem) afterLoad() {}
+
+func (x *Filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfs)
+ m.Load(1, &x.droppedDentries)
+ m.Load(2, &x.nextInoMinusOne)
+}
+
+func (x *Dentry) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.Dentry"
+}
+
+func (x *Dentry) StateFields() []string {
+ return []string{
+ "DentryRefs",
+ "vfsd",
+ "flags",
+ "parent",
+ "name",
+ "children",
+ "inode",
+ }
+}
+
+func (x *Dentry) beforeSave() {}
+
+func (x *Dentry) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.DentryRefs)
+ m.Save(1, &x.vfsd)
+ m.Save(2, &x.flags)
+ m.Save(3, &x.parent)
+ m.Save(4, &x.name)
+ m.Save(5, &x.children)
+ m.Save(6, &x.inode)
+}
+
+func (x *Dentry) afterLoad() {}
+
+func (x *Dentry) StateLoad(m state.Source) {
+ m.Load(0, &x.DentryRefs)
+ m.Load(1, &x.vfsd)
+ m.Load(2, &x.flags)
+ m.Load(3, &x.parent)
+ m.Load(4, &x.name)
+ m.Load(5, &x.children)
+ m.Load(6, &x.inode)
+}
+
func (x *slotList) StateTypeName() string {
return "pkg/sentry/fsimpl/kernfs.slotList"
}
@@ -227,6 +666,41 @@ func (x *StaticDirectoryRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *StaticSymlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/kernfs.StaticSymlink"
+}
+
+func (x *StaticSymlink) StateFields() []string {
+ return []string{
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeSymlink",
+ "InodeNoStatFS",
+ "target",
+ }
+}
+
+func (x *StaticSymlink) beforeSave() {}
+
+func (x *StaticSymlink) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.InodeAttrs)
+ m.Save(1, &x.InodeNoopRefCount)
+ m.Save(2, &x.InodeSymlink)
+ m.Save(3, &x.InodeNoStatFS)
+ m.Save(4, &x.target)
+}
+
+func (x *StaticSymlink) afterLoad() {}
+
+func (x *StaticSymlink) StateLoad(m state.Source) {
+ m.Load(0, &x.InodeAttrs)
+ m.Load(1, &x.InodeNoopRefCount)
+ m.Load(2, &x.InodeSymlink)
+ m.Load(3, &x.InodeNoStatFS)
+ m.Load(4, &x.target)
+}
+
func (x *syntheticDirectory) StateTypeName() string {
return "pkg/sentry/fsimpl/kernfs.syntheticDirectory"
}
@@ -272,9 +746,28 @@ func init() {
state.Register((*DentryRefs)(nil))
state.Register((*DynamicBytesFile)(nil))
state.Register((*DynamicBytesFD)(nil))
+ state.Register((*SeekEndConfig)(nil))
+ state.Register((*GenericDirectoryFDOptions)(nil))
+ state.Register((*GenericDirectoryFD)(nil))
+ state.Register((*InodeNoopRefCount)(nil))
+ state.Register((*InodeDirectoryNoNewChildren)(nil))
+ state.Register((*InodeNotDirectory)(nil))
+ state.Register((*InodeNoDynamicLookup)(nil))
+ state.Register((*InodeNotSymlink)(nil))
+ state.Register((*InodeAttrs)(nil))
+ state.Register((*slot)(nil))
+ state.Register((*OrderedChildrenOptions)(nil))
+ state.Register((*OrderedChildren)(nil))
+ state.Register((*renameAcrossDifferentImplementationsError)(nil))
+ state.Register((*InodeSymlink)(nil))
state.Register((*StaticDirectory)(nil))
+ state.Register((*AlwaysValid)(nil))
+ state.Register((*InodeNoStatFS)(nil))
+ state.Register((*Filesystem)(nil))
+ state.Register((*Dentry)(nil))
state.Register((*slotList)(nil))
state.Register((*slotEntry)(nil))
state.Register((*StaticDirectoryRefs)(nil))
+ state.Register((*StaticSymlink)(nil))
state.Register((*syntheticDirectory)(nil))
}
diff --git a/pkg/sentry/fsimpl/kernfs/symlink.go b/pkg/sentry/fsimpl/kernfs/symlink.go
index 443121c99..58a93eaac 100644
--- a/pkg/sentry/fsimpl/kernfs/symlink.go
+++ b/pkg/sentry/fsimpl/kernfs/symlink.go
@@ -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
diff --git a/pkg/sentry/fsimpl/overlay/directory.go b/pkg/sentry/fsimpl/overlay/directory.go
index 7ab42e71e..aea599460 100644
--- a/pkg/sentry/fsimpl/overlay/directory.go
+++ b/pkg/sentry/fsimpl/overlay/directory.go
@@ -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
}
diff --git a/pkg/sentry/fsimpl/overlay/non_directory.go b/pkg/sentry/fsimpl/overlay/non_directory.go
index 6e04705c7..50b4a50f1 100644
--- a/pkg/sentry/fsimpl/overlay/non_directory.go
+++ b/pkg/sentry/fsimpl/overlay/non_directory.go
@@ -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
diff --git a/pkg/sentry/fsimpl/overlay/overlay.go b/pkg/sentry/fsimpl/overlay/overlay.go
index d0d26185e..b03fa9121 100644
--- a/pkg/sentry/fsimpl/overlay/overlay.go
+++ b/pkg/sentry/fsimpl/overlay/overlay.go
@@ -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
diff --git a/pkg/sentry/fsimpl/overlay/overlay_state_autogen.go b/pkg/sentry/fsimpl/overlay/overlay_state_autogen.go
index 0c184964f..5fd2dc37e 100644
--- a/pkg/sentry/fsimpl/overlay/overlay_state_autogen.go
+++ b/pkg/sentry/fsimpl/overlay/overlay_state_autogen.go
@@ -1,3 +1,285 @@
// automatically generated by stateify.
package overlay
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *directoryFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/overlay.directoryFD"
+}
+
+func (x *directoryFD) StateFields() []string {
+ return []string{
+ "fileDescription",
+ "DirectoryFileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "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.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.off)
+ m.Save(4, &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.DentryMetadataFileDescriptionImpl)
+ m.Load(3, &x.off)
+ m.Load(4, &x.dirents)
+}
+
+func (x *nonDirectoryFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/overlay.nonDirectoryFD"
+}
+
+func (x *nonDirectoryFD) StateFields() []string {
+ return []string{
+ "fileDescription",
+ "copiedUp",
+ "cachedFD",
+ "cachedFlags",
+ }
+}
+
+func (x *nonDirectoryFD) beforeSave() {}
+
+func (x *nonDirectoryFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.fileDescription)
+ m.Save(1, &x.copiedUp)
+ m.Save(2, &x.cachedFD)
+ m.Save(3, &x.cachedFlags)
+}
+
+func (x *nonDirectoryFD) afterLoad() {}
+
+func (x *nonDirectoryFD) StateLoad(m state.Source) {
+ m.Load(0, &x.fileDescription)
+ m.Load(1, &x.copiedUp)
+ m.Load(2, &x.cachedFD)
+ m.Load(3, &x.cachedFlags)
+}
+
+func (x *FilesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/overlay.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/overlay.FilesystemOptions"
+}
+
+func (x *FilesystemOptions) StateFields() []string {
+ return []string{
+ "UpperRoot",
+ "LowerRoots",
+ }
+}
+
+func (x *FilesystemOptions) beforeSave() {}
+
+func (x *FilesystemOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.UpperRoot)
+ m.Save(1, &x.LowerRoots)
+}
+
+func (x *FilesystemOptions) afterLoad() {}
+
+func (x *FilesystemOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.UpperRoot)
+ m.Load(1, &x.LowerRoots)
+}
+
+func (x *filesystem) StateTypeName() string {
+ return "pkg/sentry/fsimpl/overlay.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "vfsfs",
+ "opts",
+ "creds",
+ "dirDevMinor",
+ "lowerDevMinors",
+ "lastDirIno",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfs)
+ m.Save(1, &x.opts)
+ m.Save(2, &x.creds)
+ m.Save(3, &x.dirDevMinor)
+ m.Save(4, &x.lowerDevMinors)
+ m.Save(5, &x.lastDirIno)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfs)
+ m.Load(1, &x.opts)
+ m.Load(2, &x.creds)
+ m.Load(3, &x.dirDevMinor)
+ m.Load(4, &x.lowerDevMinors)
+ m.Load(5, &x.lastDirIno)
+}
+
+func (x *dentry) StateTypeName() string {
+ return "pkg/sentry/fsimpl/overlay.dentry"
+}
+
+func (x *dentry) StateFields() []string {
+ return []string{
+ "vfsd",
+ "refs",
+ "fs",
+ "mode",
+ "uid",
+ "gid",
+ "copiedUp",
+ "parent",
+ "name",
+ "children",
+ "dirents",
+ "upperVD",
+ "lowerVDs",
+ "inlineLowerVDs",
+ "devMajor",
+ "devMinor",
+ "ino",
+ "mapsMu",
+ "lowerMappings",
+ "dataMu",
+ "wrappedMappable",
+ "isMappable",
+ "locks",
+ }
+}
+
+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.mode)
+ m.Save(4, &x.uid)
+ m.Save(5, &x.gid)
+ m.Save(6, &x.copiedUp)
+ m.Save(7, &x.parent)
+ m.Save(8, &x.name)
+ m.Save(9, &x.children)
+ m.Save(10, &x.dirents)
+ m.Save(11, &x.upperVD)
+ m.Save(12, &x.lowerVDs)
+ m.Save(13, &x.inlineLowerVDs)
+ m.Save(14, &x.devMajor)
+ m.Save(15, &x.devMinor)
+ m.Save(16, &x.ino)
+ m.Save(17, &x.mapsMu)
+ m.Save(18, &x.lowerMappings)
+ m.Save(19, &x.dataMu)
+ m.Save(20, &x.wrappedMappable)
+ m.Save(21, &x.isMappable)
+ m.Save(22, &x.locks)
+}
+
+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.mode)
+ m.Load(4, &x.uid)
+ m.Load(5, &x.gid)
+ m.Load(6, &x.copiedUp)
+ m.Load(7, &x.parent)
+ m.Load(8, &x.name)
+ m.Load(9, &x.children)
+ m.Load(10, &x.dirents)
+ m.Load(11, &x.upperVD)
+ m.Load(12, &x.lowerVDs)
+ m.Load(13, &x.inlineLowerVDs)
+ m.Load(14, &x.devMajor)
+ m.Load(15, &x.devMinor)
+ m.Load(16, &x.ino)
+ m.Load(17, &x.mapsMu)
+ m.Load(18, &x.lowerMappings)
+ m.Load(19, &x.dataMu)
+ m.Load(20, &x.wrappedMappable)
+ m.Load(21, &x.isMappable)
+ m.Load(22, &x.locks)
+}
+
+func (x *fileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/overlay.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 init() {
+ state.Register((*directoryFD)(nil))
+ state.Register((*nonDirectoryFD)(nil))
+ state.Register((*FilesystemType)(nil))
+ state.Register((*FilesystemOptions)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*dentry)(nil))
+ state.Register((*fileDescription)(nil))
+}
diff --git a/pkg/sentry/fsimpl/pipefs/pipefs.go b/pkg/sentry/fsimpl/pipefs/pipefs.go
index 33e247578..4e2da4810 100644
--- a/pkg/sentry/fsimpl/pipefs/pipefs.go
+++ b/pkg/sentry/fsimpl/pipefs/pipefs.go
@@ -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
diff --git a/pkg/sentry/fsimpl/pipefs/pipefs_state_autogen.go b/pkg/sentry/fsimpl/pipefs/pipefs_state_autogen.go
index e3e3887cd..bdb899396 100644
--- a/pkg/sentry/fsimpl/pipefs/pipefs_state_autogen.go
+++ b/pkg/sentry/fsimpl/pipefs/pipefs_state_autogen.go
@@ -1,3 +1,105 @@
// automatically generated by stateify.
package pipefs
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *filesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/pipefs.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/pipefs.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *inode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/pipefs.inode"
+}
+
+func (x *inode) StateFields() []string {
+ return []string{
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ "InodeNoopRefCount",
+ "locks",
+ "pipe",
+ "ino",
+ "uid",
+ "gid",
+ "ctime",
+ }
+}
+
+func (x *inode) beforeSave() {}
+
+func (x *inode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.InodeNotDirectory)
+ m.Save(1, &x.InodeNotSymlink)
+ m.Save(2, &x.InodeNoopRefCount)
+ m.Save(3, &x.locks)
+ m.Save(4, &x.pipe)
+ m.Save(5, &x.ino)
+ m.Save(6, &x.uid)
+ m.Save(7, &x.gid)
+ m.Save(8, &x.ctime)
+}
+
+func (x *inode) afterLoad() {}
+
+func (x *inode) StateLoad(m state.Source) {
+ m.Load(0, &x.InodeNotDirectory)
+ m.Load(1, &x.InodeNotSymlink)
+ m.Load(2, &x.InodeNoopRefCount)
+ m.Load(3, &x.locks)
+ m.Load(4, &x.pipe)
+ m.Load(5, &x.ino)
+ m.Load(6, &x.uid)
+ m.Load(7, &x.gid)
+ m.Load(8, &x.ctime)
+}
+
+func init() {
+ state.Register((*filesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*inode)(nil))
+}
diff --git a/pkg/sentry/fsimpl/proc/filesystem.go b/pkg/sentry/fsimpl/proc/filesystem.go
index 03b5941b9..05d7948ea 100644
--- a/pkg/sentry/fsimpl/proc/filesystem.go
+++ b/pkg/sentry/fsimpl/proc/filesystem.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/proc/proc_state_autogen.go b/pkg/sentry/fsimpl/proc/proc_state_autogen.go
index 60a5644f3..3eea5708c 100644
--- a/pkg/sentry/fsimpl/proc/proc_state_autogen.go
+++ b/pkg/sentry/fsimpl/proc/proc_state_autogen.go
@@ -71,6 +71,100 @@ func (x *FilesystemType) afterLoad() {}
func (x *FilesystemType) StateLoad(m state.Source) {
}
+func (x *filesystem) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *staticFile) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.staticFile"
+}
+
+func (x *staticFile) StateFields() []string {
+ return []string{
+ "DynamicBytesFile",
+ "StaticData",
+ }
+}
+
+func (x *staticFile) beforeSave() {}
+
+func (x *staticFile) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.DynamicBytesFile)
+ m.Save(1, &x.StaticData)
+}
+
+func (x *staticFile) afterLoad() {}
+
+func (x *staticFile) StateLoad(m state.Source) {
+ m.Load(0, &x.DynamicBytesFile)
+ m.Load(1, &x.StaticData)
+}
+
+func (x *InternalData) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.InternalData"
+}
+
+func (x *InternalData) StateFields() []string {
+ return []string{
+ "Cgroups",
+ }
+}
+
+func (x *InternalData) beforeSave() {}
+
+func (x *InternalData) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Cgroups)
+}
+
+func (x *InternalData) afterLoad() {}
+
+func (x *InternalData) StateLoad(m state.Source) {
+ m.Load(0, &x.Cgroups)
+}
+
+func (x *implStatFS) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.implStatFS"
+}
+
+func (x *implStatFS) StateFields() []string {
+ return []string{}
+}
+
+func (x *implStatFS) beforeSave() {}
+
+func (x *implStatFS) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *implStatFS) afterLoad() {}
+
+func (x *implStatFS) StateLoad(m state.Source) {
+}
+
func (x *subtasksInode) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.subtasksInode"
}
@@ -127,6 +221,32 @@ func (x *subtasksInode) StateLoad(m state.Source) {
m.Load(11, &x.cgroupControllers)
}
+func (x *subtasksFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.subtasksFD"
+}
+
+func (x *subtasksFD) StateFields() []string {
+ return []string{
+ "GenericDirectoryFD",
+ "task",
+ }
+}
+
+func (x *subtasksFD) beforeSave() {}
+
+func (x *subtasksFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.GenericDirectoryFD)
+ m.Save(1, &x.task)
+}
+
+func (x *subtasksFD) afterLoad() {}
+
+func (x *subtasksFD) StateLoad(m state.Source) {
+ m.Load(0, &x.GenericDirectoryFD)
+ m.Load(1, &x.task)
+}
+
func (x *subtasksInodeRefs) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.subtasksInodeRefs"
}
@@ -197,6 +317,64 @@ func (x *taskInode) StateLoad(m state.Source) {
m.Load(8, &x.task)
}
+func (x *taskOwnedInode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.taskOwnedInode"
+}
+
+func (x *taskOwnedInode) StateFields() []string {
+ return []string{
+ "Inode",
+ "owner",
+ }
+}
+
+func (x *taskOwnedInode) beforeSave() {}
+
+func (x *taskOwnedInode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Inode)
+ m.Save(1, &x.owner)
+}
+
+func (x *taskOwnedInode) afterLoad() {}
+
+func (x *taskOwnedInode) StateLoad(m state.Source) {
+ m.Load(0, &x.Inode)
+ m.Load(1, &x.owner)
+}
+
+func (x *fdDir) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.fdDir"
+}
+
+func (x *fdDir) StateFields() []string {
+ return []string{
+ "locks",
+ "fs",
+ "task",
+ "produceSymlink",
+ }
+}
+
+func (x *fdDir) beforeSave() {}
+
+func (x *fdDir) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.locks)
+ m.Save(1, &x.fs)
+ m.Save(2, &x.task)
+ m.Save(3, &x.produceSymlink)
+}
+
+func (x *fdDir) afterLoad() {}
+
+func (x *fdDir) StateLoad(m state.Source) {
+ m.Load(0, &x.locks)
+ m.Load(1, &x.fs)
+ m.Load(2, &x.task)
+ m.Load(3, &x.produceSymlink)
+}
+
func (x *fdDirInode) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.fdDirInode"
}
@@ -766,6 +944,102 @@ func (x *mountsData) StateLoad(m state.Source) {
m.Load(1, &x.task)
}
+func (x *namespaceSymlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.namespaceSymlink"
+}
+
+func (x *namespaceSymlink) StateFields() []string {
+ return []string{
+ "StaticSymlink",
+ "task",
+ }
+}
+
+func (x *namespaceSymlink) beforeSave() {}
+
+func (x *namespaceSymlink) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.StaticSymlink)
+ m.Save(1, &x.task)
+}
+
+func (x *namespaceSymlink) afterLoad() {}
+
+func (x *namespaceSymlink) StateLoad(m state.Source) {
+ m.Load(0, &x.StaticSymlink)
+ m.Load(1, &x.task)
+}
+
+func (x *namespaceInode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.namespaceInode"
+}
+
+func (x *namespaceInode) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ "locks",
+ }
+}
+
+func (x *namespaceInode) beforeSave() {}
+
+func (x *namespaceInode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeNoopRefCount)
+ m.Save(3, &x.InodeNotDirectory)
+ m.Save(4, &x.InodeNotSymlink)
+ m.Save(5, &x.locks)
+}
+
+func (x *namespaceInode) afterLoad() {}
+
+func (x *namespaceInode) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeNoopRefCount)
+ m.Load(3, &x.InodeNotDirectory)
+ m.Load(4, &x.InodeNotSymlink)
+ m.Load(5, &x.locks)
+}
+
+func (x *namespaceFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.namespaceFD"
+}
+
+func (x *namespaceFD) StateFields() []string {
+ return []string{
+ "FileDescriptionDefaultImpl",
+ "LockFD",
+ "vfsfd",
+ "inode",
+ }
+}
+
+func (x *namespaceFD) beforeSave() {}
+
+func (x *namespaceFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.FileDescriptionDefaultImpl)
+ m.Save(1, &x.LockFD)
+ m.Save(2, &x.vfsfd)
+ m.Save(3, &x.inode)
+}
+
+func (x *namespaceFD) afterLoad() {}
+
+func (x *namespaceFD) StateLoad(m state.Source) {
+ m.Load(0, &x.FileDescriptionDefaultImpl)
+ m.Load(1, &x.LockFD)
+ m.Load(2, &x.vfsfd)
+ m.Load(3, &x.inode)
+}
+
func (x *taskInodeRefs) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.taskInodeRefs"
}
@@ -971,6 +1245,32 @@ func (x *netSnmpData) StateLoad(m state.Source) {
m.Load(1, &x.stack)
}
+func (x *snmpLine) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.snmpLine"
+}
+
+func (x *snmpLine) StateFields() []string {
+ return []string{
+ "prefix",
+ "header",
+ }
+}
+
+func (x *snmpLine) beforeSave() {}
+
+func (x *snmpLine) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.prefix)
+ m.Save(1, &x.header)
+}
+
+func (x *snmpLine) afterLoad() {}
+
+func (x *snmpLine) StateLoad(m state.Source) {
+ m.Load(0, &x.prefix)
+ m.Load(1, &x.header)
+}
+
func (x *netRouteData) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.netRouteData"
}
@@ -1082,6 +1382,175 @@ func (x *tasksInode) StateLoad(m state.Source) {
m.Load(12, &x.cgroupControllers)
}
+func (x *staticFileSetStat) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.staticFileSetStat"
+}
+
+func (x *staticFileSetStat) StateFields() []string {
+ return []string{
+ "dynamicBytesFileSetAttr",
+ "StaticData",
+ }
+}
+
+func (x *staticFileSetStat) beforeSave() {}
+
+func (x *staticFileSetStat) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.dynamicBytesFileSetAttr)
+ m.Save(1, &x.StaticData)
+}
+
+func (x *staticFileSetStat) afterLoad() {}
+
+func (x *staticFileSetStat) StateLoad(m state.Source) {
+ m.Load(0, &x.dynamicBytesFileSetAttr)
+ m.Load(1, &x.StaticData)
+}
+
+func (x *selfSymlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.selfSymlink"
+}
+
+func (x *selfSymlink) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeSymlink",
+ "pidns",
+ }
+}
+
+func (x *selfSymlink) beforeSave() {}
+
+func (x *selfSymlink) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeNoopRefCount)
+ m.Save(3, &x.InodeSymlink)
+ m.Save(4, &x.pidns)
+}
+
+func (x *selfSymlink) afterLoad() {}
+
+func (x *selfSymlink) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeNoopRefCount)
+ m.Load(3, &x.InodeSymlink)
+ m.Load(4, &x.pidns)
+}
+
+func (x *threadSelfSymlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.threadSelfSymlink"
+}
+
+func (x *threadSelfSymlink) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeSymlink",
+ "pidns",
+ }
+}
+
+func (x *threadSelfSymlink) beforeSave() {}
+
+func (x *threadSelfSymlink) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeNoopRefCount)
+ m.Save(3, &x.InodeSymlink)
+ m.Save(4, &x.pidns)
+}
+
+func (x *threadSelfSymlink) afterLoad() {}
+
+func (x *threadSelfSymlink) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeNoopRefCount)
+ m.Load(3, &x.InodeSymlink)
+ m.Load(4, &x.pidns)
+}
+
+func (x *dynamicBytesFileSetAttr) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.dynamicBytesFileSetAttr"
+}
+
+func (x *dynamicBytesFileSetAttr) StateFields() []string {
+ return []string{
+ "DynamicBytesFile",
+ }
+}
+
+func (x *dynamicBytesFileSetAttr) beforeSave() {}
+
+func (x *dynamicBytesFileSetAttr) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.DynamicBytesFile)
+}
+
+func (x *dynamicBytesFileSetAttr) afterLoad() {}
+
+func (x *dynamicBytesFileSetAttr) StateLoad(m state.Source) {
+ m.Load(0, &x.DynamicBytesFile)
+}
+
+func (x *cpuStats) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.cpuStats"
+}
+
+func (x *cpuStats) StateFields() []string {
+ return []string{
+ "user",
+ "nice",
+ "system",
+ "idle",
+ "ioWait",
+ "irq",
+ "softirq",
+ "steal",
+ "guest",
+ "guestNice",
+ }
+}
+
+func (x *cpuStats) beforeSave() {}
+
+func (x *cpuStats) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.user)
+ m.Save(1, &x.nice)
+ m.Save(2, &x.system)
+ m.Save(3, &x.idle)
+ m.Save(4, &x.ioWait)
+ m.Save(5, &x.irq)
+ m.Save(6, &x.softirq)
+ m.Save(7, &x.steal)
+ m.Save(8, &x.guest)
+ m.Save(9, &x.guestNice)
+}
+
+func (x *cpuStats) afterLoad() {}
+
+func (x *cpuStats) StateLoad(m state.Source) {
+ m.Load(0, &x.user)
+ m.Load(1, &x.nice)
+ m.Load(2, &x.system)
+ m.Load(3, &x.idle)
+ m.Load(4, &x.ioWait)
+ m.Load(5, &x.irq)
+ m.Load(6, &x.softirq)
+ m.Load(7, &x.steal)
+ m.Load(8, &x.guest)
+ m.Load(9, &x.guestNice)
+}
+
func (x *statData) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.statData"
}
@@ -1243,6 +1712,14 @@ func (x *tasksInodeRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *tcpMemDir) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.tcpMemDir"
+}
+
+func (x *tcpMemDir) StateFields() []string {
+ return nil
+}
+
func (x *mmapMinAddrData) StateTypeName() string {
return "pkg/sentry/fsimpl/proc.mmapMinAddrData"
}
@@ -1409,9 +1886,16 @@ func init() {
state.Register((*fdDirInodeRefs)(nil))
state.Register((*fdInfoDirInodeRefs)(nil))
state.Register((*FilesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*staticFile)(nil))
+ state.Register((*InternalData)(nil))
+ state.Register((*implStatFS)(nil))
state.Register((*subtasksInode)(nil))
+ state.Register((*subtasksFD)(nil))
state.Register((*subtasksInodeRefs)(nil))
state.Register((*taskInode)(nil))
+ state.Register((*taskOwnedInode)(nil))
+ state.Register((*fdDir)(nil))
state.Register((*fdDirInode)(nil))
state.Register((*fdSymlink)(nil))
state.Register((*fdInfoDirInode)(nil))
@@ -1431,6 +1915,9 @@ func init() {
state.Register((*exeSymlink)(nil))
state.Register((*mountInfoData)(nil))
state.Register((*mountsData)(nil))
+ state.Register((*namespaceSymlink)(nil))
+ state.Register((*namespaceInode)(nil))
+ state.Register((*namespaceFD)(nil))
state.Register((*taskInodeRefs)(nil))
state.Register((*ifinet6)(nil))
state.Register((*netDevData)(nil))
@@ -1439,9 +1926,15 @@ func init() {
state.Register((*netTCP6Data)(nil))
state.Register((*netUDPData)(nil))
state.Register((*netSnmpData)(nil))
+ state.Register((*snmpLine)(nil))
state.Register((*netRouteData)(nil))
state.Register((*netStatData)(nil))
state.Register((*tasksInode)(nil))
+ state.Register((*staticFileSetStat)(nil))
+ state.Register((*selfSymlink)(nil))
+ state.Register((*threadSelfSymlink)(nil))
+ state.Register((*dynamicBytesFileSetAttr)(nil))
+ state.Register((*cpuStats)(nil))
state.Register((*statData)(nil))
state.Register((*loadavgData)(nil))
state.Register((*meminfoData)(nil))
@@ -1449,6 +1942,7 @@ func init() {
state.Register((*versionData)(nil))
state.Register((*filesystemsData)(nil))
state.Register((*tasksInodeRefs)(nil))
+ state.Register((*tcpMemDir)(nil))
state.Register((*mmapMinAddrData)(nil))
state.Register((*hostnameData)(nil))
state.Register((*tcpSackData)(nil))
diff --git a/pkg/sentry/fsimpl/proc/subtasks.go b/pkg/sentry/fsimpl/proc/subtasks.go
index 47dc0ac9a..47ecd941c 100644
--- a/pkg/sentry/fsimpl/proc/subtasks.go
+++ b/pkg/sentry/fsimpl/proc/subtasks.go
@@ -116,6 +116,7 @@ func (i *subtasksInode) IterDirents(ctx context.Context, cb vfs.IterDirentsCallb
return offset, nil
}
+// +stateify savable
type subtasksFD struct {
kernfs.GenericDirectoryFD
diff --git a/pkg/sentry/fsimpl/proc/task.go b/pkg/sentry/fsimpl/proc/task.go
index ae461bb48..1f99183eb 100644
--- a/pkg/sentry/fsimpl/proc/task.go
+++ b/pkg/sentry/fsimpl/proc/task.go
@@ -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
diff --git a/pkg/sentry/fsimpl/proc/task_fds.go b/pkg/sentry/fsimpl/proc/task_fds.go
index c7104458f..0866cea2b 100644
--- a/pkg/sentry/fsimpl/proc/task_fds.go
+++ b/pkg/sentry/fsimpl/proc/task_fds.go
@@ -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
diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go
index feed5bc3f..b81c8279e 100644
--- a/pkg/sentry/fsimpl/proc/task_files.go
+++ b/pkg/sentry/fsimpl/proc/task_files.go
@@ -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
diff --git a/pkg/sentry/fsimpl/proc/task_net.go b/pkg/sentry/fsimpl/proc/task_net.go
index 1607eac19..e7f748655 100644
--- a/pkg/sentry/fsimpl/proc/task_net.go
+++ b/pkg/sentry/fsimpl/proc/task_net.go
@@ -616,6 +616,7 @@ type netSnmpData struct {
var _ dynamicInode = (*netSnmpData)(nil)
+// +stateify savable
type snmpLine struct {
prefix string
header string
diff --git a/pkg/sentry/fsimpl/proc/tasks.go b/pkg/sentry/fsimpl/proc/tasks.go
index ad08c3626..d8f5dd509 100644
--- a/pkg/sentry/fsimpl/proc/tasks.go
+++ b/pkg/sentry/fsimpl/proc/tasks.go
@@ -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
diff --git a/pkg/sentry/fsimpl/proc/tasks_files.go b/pkg/sentry/fsimpl/proc/tasks_files.go
index 459a8e52e..f268c59b0 100644
--- a/pkg/sentry/fsimpl/proc/tasks_files.go
+++ b/pkg/sentry/fsimpl/proc/tasks_files.go
@@ -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
diff --git a/pkg/sentry/fsimpl/proc/tasks_sys.go b/pkg/sentry/fsimpl/proc/tasks_sys.go
index a3ffbb15e..3312b0418 100644
--- a/pkg/sentry/fsimpl/proc/tasks_sys.go
+++ b/pkg/sentry/fsimpl/proc/tasks_sys.go
@@ -31,6 +31,7 @@ import (
"gvisor.dev/gvisor/pkg/usermem"
)
+// +stateify savable
type tcpMemDir int
const (
diff --git a/pkg/sentry/fsimpl/signalfd/signalfd.go b/pkg/sentry/fsimpl/signalfd/signalfd.go
index 3c02af8c9..bf11b425a 100644
--- a/pkg/sentry/fsimpl/signalfd/signalfd.go
+++ b/pkg/sentry/fsimpl/signalfd/signalfd.go
@@ -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
diff --git a/pkg/sentry/fsimpl/signalfd/signalfd_state_autogen.go b/pkg/sentry/fsimpl/signalfd/signalfd_state_autogen.go
index c3d9b2ffb..acd2ff5b4 100644
--- a/pkg/sentry/fsimpl/signalfd/signalfd_state_autogen.go
+++ b/pkg/sentry/fsimpl/signalfd/signalfd_state_autogen.go
@@ -1,3 +1,49 @@
// automatically generated by stateify.
package signalfd
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *SignalFileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/signalfd.SignalFileDescription"
+}
+
+func (x *SignalFileDescription) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ "target",
+ "mask",
+ }
+}
+
+func (x *SignalFileDescription) beforeSave() {}
+
+func (x *SignalFileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+ m.Save(4, &x.target)
+ m.Save(5, &x.mask)
+}
+
+func (x *SignalFileDescription) afterLoad() {}
+
+func (x *SignalFileDescription) 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.target)
+ m.Load(5, &x.mask)
+}
+
+func init() {
+ state.Register((*SignalFileDescription)(nil))
+}
diff --git a/pkg/sentry/fsimpl/sockfs/sockfs.go b/pkg/sentry/fsimpl/sockfs/sockfs.go
index f1e75e277..29e5371d6 100644
--- a/pkg/sentry/fsimpl/sockfs/sockfs.go
+++ b/pkg/sentry/fsimpl/sockfs/sockfs.go
@@ -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
diff --git a/pkg/sentry/fsimpl/sockfs/sockfs_state_autogen.go b/pkg/sentry/fsimpl/sockfs/sockfs_state_autogen.go
index 8d5b85e2c..bbc868a48 100644
--- a/pkg/sentry/fsimpl/sockfs/sockfs_state_autogen.go
+++ b/pkg/sentry/fsimpl/sockfs/sockfs_state_autogen.go
@@ -1,3 +1,90 @@
// automatically generated by stateify.
package sockfs
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *filesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sockfs.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/sockfs.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *inode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sockfs.inode"
+}
+
+func (x *inode) StateFields() []string {
+ return []string{
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ }
+}
+
+func (x *inode) beforeSave() {}
+
+func (x *inode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.InodeAttrs)
+ m.Save(1, &x.InodeNoopRefCount)
+ m.Save(2, &x.InodeNotDirectory)
+ m.Save(3, &x.InodeNotSymlink)
+}
+
+func (x *inode) afterLoad() {}
+
+func (x *inode) StateLoad(m state.Source) {
+ m.Load(0, &x.InodeAttrs)
+ m.Load(1, &x.InodeNoopRefCount)
+ m.Load(2, &x.InodeNotDirectory)
+ m.Load(3, &x.InodeNotSymlink)
+}
+
+func init() {
+ state.Register((*filesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*inode)(nil))
+}
diff --git a/pkg/sentry/fsimpl/sys/kcov.go b/pkg/sentry/fsimpl/sys/kcov.go
index 252f75d26..b75d70ae6 100644
--- a/pkg/sentry/fsimpl/sys/kcov.go
+++ b/pkg/sentry/fsimpl/sys/kcov.go
@@ -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
diff --git a/pkg/sentry/fsimpl/sys/sys.go b/pkg/sentry/fsimpl/sys/sys.go
index 8bcefc103..1568c581f 100644
--- a/pkg/sentry/fsimpl/sys/sys.go
+++ b/pkg/sentry/fsimpl/sys/sys.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/sys/sys_state_autogen.go b/pkg/sentry/fsimpl/sys/sys_state_autogen.go
index 347a46318..14d4efce9 100644
--- a/pkg/sentry/fsimpl/sys/sys_state_autogen.go
+++ b/pkg/sentry/fsimpl/sys/sys_state_autogen.go
@@ -29,6 +29,220 @@ func (x *dirRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *kcovInode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sys.kcovInode"
+}
+
+func (x *kcovInode) StateFields() []string {
+ return []string{
+ "InodeAttrs",
+ "InodeNoopRefCount",
+ "InodeNotDirectory",
+ "InodeNotSymlink",
+ "implStatFS",
+ }
+}
+
+func (x *kcovInode) beforeSave() {}
+
+func (x *kcovInode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.InodeAttrs)
+ m.Save(1, &x.InodeNoopRefCount)
+ m.Save(2, &x.InodeNotDirectory)
+ m.Save(3, &x.InodeNotSymlink)
+ m.Save(4, &x.implStatFS)
+}
+
+func (x *kcovInode) afterLoad() {}
+
+func (x *kcovInode) StateLoad(m state.Source) {
+ m.Load(0, &x.InodeAttrs)
+ m.Load(1, &x.InodeNoopRefCount)
+ m.Load(2, &x.InodeNotDirectory)
+ m.Load(3, &x.InodeNotSymlink)
+ m.Load(4, &x.implStatFS)
+}
+
+func (x *kcovFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sys.kcovFD"
+}
+
+func (x *kcovFD) StateFields() []string {
+ return []string{
+ "FileDescriptionDefaultImpl",
+ "NoLockFD",
+ "vfsfd",
+ "inode",
+ "kcov",
+ }
+}
+
+func (x *kcovFD) beforeSave() {}
+
+func (x *kcovFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.FileDescriptionDefaultImpl)
+ m.Save(1, &x.NoLockFD)
+ m.Save(2, &x.vfsfd)
+ m.Save(3, &x.inode)
+ m.Save(4, &x.kcov)
+}
+
+func (x *kcovFD) afterLoad() {}
+
+func (x *kcovFD) StateLoad(m state.Source) {
+ m.Load(0, &x.FileDescriptionDefaultImpl)
+ m.Load(1, &x.NoLockFD)
+ m.Load(2, &x.vfsfd)
+ m.Load(3, &x.inode)
+ m.Load(4, &x.kcov)
+}
+
+func (x *FilesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sys.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/sys.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "Filesystem",
+ "devMinor",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Filesystem)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.Filesystem)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *dir) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sys.dir"
+}
+
+func (x *dir) StateFields() []string {
+ return []string{
+ "dirRefs",
+ "InodeAttrs",
+ "InodeNoDynamicLookup",
+ "InodeNotSymlink",
+ "InodeDirectoryNoNewChildren",
+ "OrderedChildren",
+ "locks",
+ "dentry",
+ }
+}
+
+func (x *dir) beforeSave() {}
+
+func (x *dir) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.dirRefs)
+ m.Save(1, &x.InodeAttrs)
+ m.Save(2, &x.InodeNoDynamicLookup)
+ m.Save(3, &x.InodeNotSymlink)
+ m.Save(4, &x.InodeDirectoryNoNewChildren)
+ m.Save(5, &x.OrderedChildren)
+ m.Save(6, &x.locks)
+ m.Save(7, &x.dentry)
+}
+
+func (x *dir) afterLoad() {}
+
+func (x *dir) StateLoad(m state.Source) {
+ m.Load(0, &x.dirRefs)
+ m.Load(1, &x.InodeAttrs)
+ m.Load(2, &x.InodeNoDynamicLookup)
+ m.Load(3, &x.InodeNotSymlink)
+ m.Load(4, &x.InodeDirectoryNoNewChildren)
+ m.Load(5, &x.OrderedChildren)
+ m.Load(6, &x.locks)
+ m.Load(7, &x.dentry)
+}
+
+func (x *cpuFile) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sys.cpuFile"
+}
+
+func (x *cpuFile) StateFields() []string {
+ return []string{
+ "implStatFS",
+ "DynamicBytesFile",
+ "maxCores",
+ }
+}
+
+func (x *cpuFile) beforeSave() {}
+
+func (x *cpuFile) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.implStatFS)
+ m.Save(1, &x.DynamicBytesFile)
+ m.Save(2, &x.maxCores)
+}
+
+func (x *cpuFile) afterLoad() {}
+
+func (x *cpuFile) StateLoad(m state.Source) {
+ m.Load(0, &x.implStatFS)
+ m.Load(1, &x.DynamicBytesFile)
+ m.Load(2, &x.maxCores)
+}
+
+func (x *implStatFS) StateTypeName() string {
+ return "pkg/sentry/fsimpl/sys.implStatFS"
+}
+
+func (x *implStatFS) StateFields() []string {
+ return []string{}
+}
+
+func (x *implStatFS) beforeSave() {}
+
+func (x *implStatFS) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *implStatFS) afterLoad() {}
+
+func (x *implStatFS) StateLoad(m state.Source) {
+}
+
func init() {
state.Register((*dirRefs)(nil))
+ state.Register((*kcovInode)(nil))
+ state.Register((*kcovFD)(nil))
+ state.Register((*FilesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*dir)(nil))
+ state.Register((*cpuFile)(nil))
+ state.Register((*implStatFS)(nil))
}
diff --git a/pkg/sentry/fsimpl/timerfd/timerfd.go b/pkg/sentry/fsimpl/timerfd/timerfd.go
index ac8a4e3bb..8853c8ad2 100644
--- a/pkg/sentry/fsimpl/timerfd/timerfd.go
+++ b/pkg/sentry/fsimpl/timerfd/timerfd.go
@@ -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
diff --git a/pkg/sentry/fsimpl/timerfd/timerfd_state_autogen.go b/pkg/sentry/fsimpl/timerfd/timerfd_state_autogen.go
index 4e5976369..722153ff8 100644
--- a/pkg/sentry/fsimpl/timerfd/timerfd_state_autogen.go
+++ b/pkg/sentry/fsimpl/timerfd/timerfd_state_autogen.go
@@ -1,3 +1,52 @@
// automatically generated by stateify.
package timerfd
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (x *TimerFileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/timerfd.TimerFileDescription"
+}
+
+func (x *TimerFileDescription) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ "events",
+ "timer",
+ "val",
+ }
+}
+
+func (x *TimerFileDescription) beforeSave() {}
+
+func (x *TimerFileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+ m.Save(4, &x.events)
+ m.Save(5, &x.timer)
+ m.Save(6, &x.val)
+}
+
+func (x *TimerFileDescription) afterLoad() {}
+
+func (x *TimerFileDescription) 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.events)
+ m.Load(5, &x.timer)
+ m.Load(6, &x.val)
+}
+
+func init() {
+ state.Register((*TimerFileDescription)(nil))
+}
diff --git a/pkg/sentry/fsimpl/tmpfs/device_file.go b/pkg/sentry/fsimpl/tmpfs/device_file.go
index ac54d420d..9129d35b7 100644
--- a/pkg/sentry/fsimpl/tmpfs/device_file.go
+++ b/pkg/sentry/fsimpl/tmpfs/device_file.go
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/vfs"
)
+// +stateify savable
type deviceFile struct {
inode inode
kind vfs.DeviceKind
diff --git a/pkg/sentry/fsimpl/tmpfs/directory.go b/pkg/sentry/fsimpl/tmpfs/directory.go
index 070c75e68..e90669cf0 100644
--- a/pkg/sentry/fsimpl/tmpfs/directory.go
+++ b/pkg/sentry/fsimpl/tmpfs/directory.go
@@ -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
diff --git a/pkg/sentry/fsimpl/tmpfs/named_pipe.go b/pkg/sentry/fsimpl/tmpfs/named_pipe.go
index 5b0471ff4..d772db9e9 100644
--- a/pkg/sentry/fsimpl/tmpfs/named_pipe.go
+++ b/pkg/sentry/fsimpl/tmpfs/named_pipe.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/usermem"
)
+// +stateify savable
type namedPipe struct {
inode inode
diff --git a/pkg/sentry/fsimpl/tmpfs/regular_file.go b/pkg/sentry/fsimpl/tmpfs/regular_file.go
index b8699d064..a199eb33d 100644
--- a/pkg/sentry/fsimpl/tmpfs/regular_file.go
+++ b/pkg/sentry/fsimpl/tmpfs/regular_file.go
@@ -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.
diff --git a/pkg/sentry/fsimpl/tmpfs/socket_file.go b/pkg/sentry/fsimpl/tmpfs/socket_file.go
index 3ed650474..5699d5975 100644
--- a/pkg/sentry/fsimpl/tmpfs/socket_file.go
+++ b/pkg/sentry/fsimpl/tmpfs/socket_file.go
@@ -21,6 +21,8 @@ import (
)
// socketFile is a socket (=S_IFSOCK) tmpfs file.
+//
+// +stateify savable
type socketFile struct {
inode inode
ep transport.BoundEndpoint
diff --git a/pkg/sentry/fsimpl/tmpfs/symlink.go b/pkg/sentry/fsimpl/tmpfs/symlink.go
index b0de5fabe..a102a2ee2 100644
--- a/pkg/sentry/fsimpl/tmpfs/symlink.go
+++ b/pkg/sentry/fsimpl/tmpfs/symlink.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
)
+// +stateify savable
type symlink struct {
inode inode
target string // immutable
diff --git a/pkg/sentry/fsimpl/tmpfs/tmpfs.go b/pkg/sentry/fsimpl/tmpfs/tmpfs.go
index 4658e1533..cefec8fde 100644
--- a/pkg/sentry/fsimpl/tmpfs/tmpfs.go
+++ b/pkg/sentry/fsimpl/tmpfs/tmpfs.go
@@ -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
diff --git a/pkg/sentry/fsimpl/tmpfs/tmpfs_state_autogen.go b/pkg/sentry/fsimpl/tmpfs/tmpfs_state_autogen.go
index d88136656..4252b95e6 100644
--- a/pkg/sentry/fsimpl/tmpfs/tmpfs_state_autogen.go
+++ b/pkg/sentry/fsimpl/tmpfs/tmpfs_state_autogen.go
@@ -58,6 +58,105 @@ func (x *dentryEntry) StateLoad(m state.Source) {
m.Load(1, &x.prev)
}
+func (x *deviceFile) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.deviceFile"
+}
+
+func (x *deviceFile) StateFields() []string {
+ return []string{
+ "inode",
+ "kind",
+ "major",
+ "minor",
+ }
+}
+
+func (x *deviceFile) beforeSave() {}
+
+func (x *deviceFile) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inode)
+ m.Save(1, &x.kind)
+ m.Save(2, &x.major)
+ m.Save(3, &x.minor)
+}
+
+func (x *deviceFile) afterLoad() {}
+
+func (x *deviceFile) StateLoad(m state.Source) {
+ m.Load(0, &x.inode)
+ m.Load(1, &x.kind)
+ m.Load(2, &x.major)
+ m.Load(3, &x.minor)
+}
+
+func (x *directory) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.directory"
+}
+
+func (x *directory) StateFields() []string {
+ return []string{
+ "dentry",
+ "inode",
+ "childMap",
+ "numChildren",
+ "childList",
+ }
+}
+
+func (x *directory) beforeSave() {}
+
+func (x *directory) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.dentry)
+ m.Save(1, &x.inode)
+ m.Save(2, &x.childMap)
+ m.Save(3, &x.numChildren)
+ m.Save(4, &x.childList)
+}
+
+func (x *directory) afterLoad() {}
+
+func (x *directory) StateLoad(m state.Source) {
+ m.Load(0, &x.dentry)
+ m.Load(1, &x.inode)
+ m.Load(2, &x.childMap)
+ m.Load(3, &x.numChildren)
+ m.Load(4, &x.childList)
+}
+
+func (x *directoryFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.directoryFD"
+}
+
+func (x *directoryFD) StateFields() []string {
+ return []string{
+ "fileDescription",
+ "DirectoryFileDescriptionDefaultImpl",
+ "iter",
+ "off",
+ }
+}
+
+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.iter)
+ m.Save(3, &x.off)
+}
+
+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.iter)
+ m.Load(3, &x.off)
+}
+
func (x *inodeRefs) StateTypeName() string {
return "pkg/sentry/fsimpl/tmpfs.inodeRefs"
}
@@ -81,8 +180,379 @@ func (x *inodeRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *namedPipe) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.namedPipe"
+}
+
+func (x *namedPipe) StateFields() []string {
+ return []string{
+ "inode",
+ "pipe",
+ }
+}
+
+func (x *namedPipe) beforeSave() {}
+
+func (x *namedPipe) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inode)
+ m.Save(1, &x.pipe)
+}
+
+func (x *namedPipe) afterLoad() {}
+
+func (x *namedPipe) StateLoad(m state.Source) {
+ m.Load(0, &x.inode)
+ m.Load(1, &x.pipe)
+}
+
+func (x *regularFile) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.regularFile"
+}
+
+func (x *regularFile) StateFields() []string {
+ return []string{
+ "inode",
+ "memFile",
+ "memoryUsageKind",
+ "mappings",
+ "writableMappingPages",
+ "data",
+ "seals",
+ "size",
+ }
+}
+
+func (x *regularFile) beforeSave() {}
+
+func (x *regularFile) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inode)
+ m.Save(1, &x.memFile)
+ m.Save(2, &x.memoryUsageKind)
+ m.Save(3, &x.mappings)
+ m.Save(4, &x.writableMappingPages)
+ m.Save(5, &x.data)
+ m.Save(6, &x.seals)
+ m.Save(7, &x.size)
+}
+
+func (x *regularFile) afterLoad() {}
+
+func (x *regularFile) StateLoad(m state.Source) {
+ m.Load(0, &x.inode)
+ m.Load(1, &x.memFile)
+ m.Load(2, &x.memoryUsageKind)
+ m.Load(3, &x.mappings)
+ m.Load(4, &x.writableMappingPages)
+ m.Load(5, &x.data)
+ m.Load(6, &x.seals)
+ m.Load(7, &x.size)
+}
+
+func (x *regularFileFD) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.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 *socketFile) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.socketFile"
+}
+
+func (x *socketFile) StateFields() []string {
+ return []string{
+ "inode",
+ "ep",
+ }
+}
+
+func (x *socketFile) beforeSave() {}
+
+func (x *socketFile) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inode)
+ m.Save(1, &x.ep)
+}
+
+func (x *socketFile) afterLoad() {}
+
+func (x *socketFile) StateLoad(m state.Source) {
+ m.Load(0, &x.inode)
+ m.Load(1, &x.ep)
+}
+
+func (x *symlink) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.symlink"
+}
+
+func (x *symlink) StateFields() []string {
+ return []string{
+ "inode",
+ "target",
+ }
+}
+
+func (x *symlink) beforeSave() {}
+
+func (x *symlink) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.inode)
+ m.Save(1, &x.target)
+}
+
+func (x *symlink) afterLoad() {}
+
+func (x *symlink) StateLoad(m state.Source) {
+ m.Load(0, &x.inode)
+ m.Load(1, &x.target)
+}
+
+func (x *FilesystemType) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.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/tmpfs.filesystem"
+}
+
+func (x *filesystem) StateFields() []string {
+ return []string{
+ "vfsfs",
+ "memFile",
+ "clock",
+ "devMinor",
+ "nextInoMinusOne",
+ }
+}
+
+func (x *filesystem) beforeSave() {}
+
+func (x *filesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfs)
+ m.Save(1, &x.memFile)
+ m.Save(2, &x.clock)
+ m.Save(3, &x.devMinor)
+ m.Save(4, &x.nextInoMinusOne)
+}
+
+func (x *filesystem) afterLoad() {}
+
+func (x *filesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfs)
+ m.Load(1, &x.memFile)
+ m.Load(2, &x.clock)
+ m.Load(3, &x.devMinor)
+ m.Load(4, &x.nextInoMinusOne)
+}
+
+func (x *FilesystemOpts) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.FilesystemOpts"
+}
+
+func (x *FilesystemOpts) StateFields() []string {
+ return []string{
+ "RootFileType",
+ "RootSymlinkTarget",
+ "FilesystemType",
+ }
+}
+
+func (x *FilesystemOpts) beforeSave() {}
+
+func (x *FilesystemOpts) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.RootFileType)
+ m.Save(1, &x.RootSymlinkTarget)
+ m.Save(2, &x.FilesystemType)
+}
+
+func (x *FilesystemOpts) afterLoad() {}
+
+func (x *FilesystemOpts) StateLoad(m state.Source) {
+ m.Load(0, &x.RootFileType)
+ m.Load(1, &x.RootSymlinkTarget)
+ m.Load(2, &x.FilesystemType)
+}
+
+func (x *dentry) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.dentry"
+}
+
+func (x *dentry) StateFields() []string {
+ return []string{
+ "vfsd",
+ "parent",
+ "name",
+ "dentryEntry",
+ "inode",
+ }
+}
+
+func (x *dentry) beforeSave() {}
+
+func (x *dentry) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsd)
+ m.Save(1, &x.parent)
+ m.Save(2, &x.name)
+ m.Save(3, &x.dentryEntry)
+ m.Save(4, &x.inode)
+}
+
+func (x *dentry) afterLoad() {}
+
+func (x *dentry) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsd)
+ m.Load(1, &x.parent)
+ m.Load(2, &x.name)
+ m.Load(3, &x.dentryEntry)
+ m.Load(4, &x.inode)
+}
+
+func (x *inode) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.inode"
+}
+
+func (x *inode) StateFields() []string {
+ return []string{
+ "fs",
+ "refs",
+ "xattrs",
+ "mode",
+ "nlink",
+ "uid",
+ "gid",
+ "ino",
+ "atime",
+ "ctime",
+ "mtime",
+ "locks",
+ "watches",
+ "impl",
+ }
+}
+
+func (x *inode) beforeSave() {}
+
+func (x *inode) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.fs)
+ m.Save(1, &x.refs)
+ m.Save(2, &x.xattrs)
+ m.Save(3, &x.mode)
+ m.Save(4, &x.nlink)
+ m.Save(5, &x.uid)
+ m.Save(6, &x.gid)
+ m.Save(7, &x.ino)
+ m.Save(8, &x.atime)
+ m.Save(9, &x.ctime)
+ m.Save(10, &x.mtime)
+ m.Save(11, &x.locks)
+ m.Save(12, &x.watches)
+ m.Save(13, &x.impl)
+}
+
+func (x *inode) afterLoad() {}
+
+func (x *inode) StateLoad(m state.Source) {
+ m.Load(0, &x.fs)
+ m.Load(1, &x.refs)
+ m.Load(2, &x.xattrs)
+ m.Load(3, &x.mode)
+ m.Load(4, &x.nlink)
+ m.Load(5, &x.uid)
+ m.Load(6, &x.gid)
+ m.Load(7, &x.ino)
+ m.Load(8, &x.atime)
+ m.Load(9, &x.ctime)
+ m.Load(10, &x.mtime)
+ m.Load(11, &x.locks)
+ m.Load(12, &x.watches)
+ m.Load(13, &x.impl)
+}
+
+func (x *fileDescription) StateTypeName() string {
+ return "pkg/sentry/fsimpl/tmpfs.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 init() {
state.Register((*dentryList)(nil))
state.Register((*dentryEntry)(nil))
+ state.Register((*deviceFile)(nil))
+ state.Register((*directory)(nil))
+ state.Register((*directoryFD)(nil))
state.Register((*inodeRefs)(nil))
+ state.Register((*namedPipe)(nil))
+ state.Register((*regularFile)(nil))
+ state.Register((*regularFileFD)(nil))
+ state.Register((*socketFile)(nil))
+ state.Register((*symlink)(nil))
+ state.Register((*FilesystemType)(nil))
+ state.Register((*filesystem)(nil))
+ state.Register((*FilesystemOpts)(nil))
+ state.Register((*dentry)(nil))
+ state.Register((*inode)(nil))
+ state.Register((*fileDescription)(nil))
}
diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go
index 22f9bb006..08bb5bd12 100644
--- a/pkg/sentry/kernel/kernel.go
+++ b/pkg/sentry/kernel/kernel.go
@@ -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
diff --git a/pkg/sentry/socket/unix/unix_state_autogen.go b/pkg/sentry/socket/unix/unix_state_autogen.go
index 6966529c6..89d78a9ad 100644
--- a/pkg/sentry/socket/unix/unix_state_autogen.go
+++ b/pkg/sentry/socket/unix/unix_state_autogen.go
@@ -90,8 +90,44 @@ func (x *socketOpsCommon) StateLoad(m state.Source) {
m.Load(5, &x.abstractNamespace)
}
+func (x *SocketVFS2) StateTypeName() string {
+ return "pkg/sentry/socket/unix.SocketVFS2"
+}
+
+func (x *SocketVFS2) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "LockFD",
+ "socketOpsCommon",
+ }
+}
+
+func (x *SocketVFS2) beforeSave() {}
+
+func (x *SocketVFS2) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.LockFD)
+ m.Save(4, &x.socketOpsCommon)
+}
+
+func (x *SocketVFS2) afterLoad() {}
+
+func (x *SocketVFS2) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfd)
+ m.Load(1, &x.FileDescriptionDefaultImpl)
+ m.Load(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Load(3, &x.LockFD)
+ m.Load(4, &x.socketOpsCommon)
+}
+
func init() {
state.Register((*socketOpsCommonRefs)(nil))
state.Register((*SocketOperations)(nil))
state.Register((*socketOpsCommon)(nil))
+ state.Register((*SocketVFS2)(nil))
}
diff --git a/pkg/sentry/socket/unix/unix_vfs2.go b/pkg/sentry/socket/unix/unix_vfs2.go
index 3688f22d2..b76c0e6fb 100644
--- a/pkg/sentry/socket/unix/unix_vfs2.go
+++ b/pkg/sentry/socket/unix/unix_vfs2.go
@@ -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
diff --git a/pkg/sentry/state/state.go b/pkg/sentry/state/state.go
index a06c9b8ab..245d2c5cf 100644
--- a/pkg/sentry/state/state.go
+++ b/pkg/sentry/state/state.go
@@ -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()
diff --git a/pkg/sentry/vfs/anonfs.go b/pkg/sentry/vfs/anonfs.go
index 9c4db3047..bdfd3ca8f 100644
--- a/pkg/sentry/vfs/anonfs.go
+++ b/pkg/sentry/vfs/anonfs.go
@@ -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
diff --git a/pkg/sentry/vfs/dentry.go b/pkg/sentry/vfs/dentry.go
index a69a5b2f1..320ab7ce1 100644
--- a/pkg/sentry/vfs/dentry.go
+++ b/pkg/sentry/vfs/dentry.go
@@ -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.
diff --git a/pkg/sentry/vfs/device.go b/pkg/sentry/vfs/device.go
index 1e9dffc8f..dde2ad79b 100644
--- a/pkg/sentry/vfs/device.go
+++ b/pkg/sentry/vfs/device.go
@@ -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
diff --git a/pkg/sentry/vfs/epoll.go b/pkg/sentry/vfs/epoll.go
index 754e76aec..8f36c3e3b 100644
--- a/pkg/sentry/vfs/epoll.go
+++ b/pkg/sentry/vfs/epoll.go
@@ -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
diff --git a/pkg/sentry/vfs/file_description.go b/pkg/sentry/vfs/file_description.go
index 73bb36d3e..1eba0270f 100644
--- a/pkg/sentry/vfs/file_description.go
+++ b/pkg/sentry/vfs/file_description.go
@@ -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
diff --git a/pkg/sentry/vfs/file_description_impl_util.go b/pkg/sentry/vfs/file_description_impl_util.go
index 78da16bac..48ca9de44 100644
--- a/pkg/sentry/vfs/file_description_impl_util.go
+++ b/pkg/sentry/vfs/file_description_impl_util.go
@@ -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.
diff --git a/pkg/sentry/vfs/filesystem.go b/pkg/sentry/vfs/filesystem.go
index 7dae4e7e8..c93d94634 100644
--- a/pkg/sentry/vfs/filesystem.go
+++ b/pkg/sentry/vfs/filesystem.go
@@ -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.
diff --git a/pkg/sentry/vfs/filesystem_type.go b/pkg/sentry/vfs/filesystem_type.go
index 82ae35fdc..bc19db1d5 100644
--- a/pkg/sentry/vfs/filesystem_type.go
+++ b/pkg/sentry/vfs/filesystem_type.go
@@ -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
diff --git a/pkg/sentry/vfs/inotify.go b/pkg/sentry/vfs/inotify.go
index aff220a61..3f0b8f45b 100644
--- a/pkg/sentry/vfs/inotify.go
+++ b/pkg/sentry/vfs/inotify.go
@@ -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
diff --git a/pkg/sentry/vfs/lock.go b/pkg/sentry/vfs/lock.go
index 42666eebf..55783d4eb 100644
--- a/pkg/sentry/vfs/lock.go
+++ b/pkg/sentry/vfs/lock.go
@@ -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
diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go
index 9da09d4c1..dfc3ae6c0 100644
--- a/pkg/sentry/vfs/mount.go
+++ b/pkg/sentry/vfs/mount.go
@@ -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]--
diff --git a/pkg/sentry/vfs/mount_unsafe.go b/pkg/sentry/vfs/mount_unsafe.go
index da2a2e9c4..b7d122d22 100644
--- a/pkg/sentry/vfs/mount_unsafe.go
+++ b/pkg/sentry/vfs/mount_unsafe.go
@@ -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
}
diff --git a/pkg/sentry/vfs/options.go b/pkg/sentry/vfs/options.go
index 413cfb101..bc79e5ecc 100644
--- a/pkg/sentry/vfs/options.go
+++ b/pkg/sentry/vfs/options.go
@@ -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
diff --git a/pkg/sentry/vfs/permissions.go b/pkg/sentry/vfs/permissions.go
index 00eeb8842..d48520d58 100644
--- a/pkg/sentry/vfs/permissions.go
+++ b/pkg/sentry/vfs/permissions.go
@@ -26,6 +26,8 @@ import (
)
// AccessTypes is a bitmask of Unix file permissions.
+//
+// +stateify savable
type AccessTypes uint16
// Bits in AccessTypes.
diff --git a/pkg/sentry/vfs/resolving_path.go b/pkg/sentry/vfs/resolving_path.go
index 3304372d9..e4fd55012 100644
--- a/pkg/sentry/vfs/resolving_path.go
+++ b/pkg/sentry/vfs/resolving_path.go
@@ -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.
diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go
index 1ebf355ef..5bd756ea5 100644
--- a/pkg/sentry/vfs/vfs.go
+++ b/pkg/sentry/vfs/vfs.go
@@ -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.
diff --git a/pkg/sentry/vfs/vfs_state_autogen.go b/pkg/sentry/vfs/vfs_state_autogen.go
index be649f60a..3c35d1577 100644
--- a/pkg/sentry/vfs/vfs_state_autogen.go
+++ b/pkg/sentry/vfs/vfs_state_autogen.go
@@ -6,6 +6,77 @@ import (
"gvisor.dev/gvisor/pkg/state"
)
+func (x *anonFilesystemType) StateTypeName() string {
+ return "pkg/sentry/vfs.anonFilesystemType"
+}
+
+func (x *anonFilesystemType) StateFields() []string {
+ return []string{}
+}
+
+func (x *anonFilesystemType) beforeSave() {}
+
+func (x *anonFilesystemType) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *anonFilesystemType) afterLoad() {}
+
+func (x *anonFilesystemType) StateLoad(m state.Source) {
+}
+
+func (x *anonFilesystem) StateTypeName() string {
+ return "pkg/sentry/vfs.anonFilesystem"
+}
+
+func (x *anonFilesystem) StateFields() []string {
+ return []string{
+ "vfsfs",
+ "devMinor",
+ }
+}
+
+func (x *anonFilesystem) beforeSave() {}
+
+func (x *anonFilesystem) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfs)
+ m.Save(1, &x.devMinor)
+}
+
+func (x *anonFilesystem) afterLoad() {}
+
+func (x *anonFilesystem) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsfs)
+ m.Load(1, &x.devMinor)
+}
+
+func (x *anonDentry) StateTypeName() string {
+ return "pkg/sentry/vfs.anonDentry"
+}
+
+func (x *anonDentry) StateFields() []string {
+ return []string{
+ "vfsd",
+ "name",
+ }
+}
+
+func (x *anonDentry) beforeSave() {}
+
+func (x *anonDentry) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsd)
+ m.Save(1, &x.name)
+}
+
+func (x *anonDentry) afterLoad() {}
+
+func (x *anonDentry) StateLoad(m state.Source) {
+ m.Load(0, &x.vfsd)
+ m.Load(1, &x.name)
+}
+
func (x *Dentry) StateTypeName() string {
return "pkg/sentry/vfs.Dentry"
}
@@ -35,6 +106,43 @@ func (x *Dentry) StateLoad(m state.Source) {
m.Load(2, &x.impl)
}
+func (x *DeviceKind) StateTypeName() string {
+ return "pkg/sentry/vfs.DeviceKind"
+}
+
+func (x *DeviceKind) StateFields() []string {
+ return nil
+}
+
+func (x *devTuple) StateTypeName() string {
+ return "pkg/sentry/vfs.devTuple"
+}
+
+func (x *devTuple) StateFields() []string {
+ return []string{
+ "kind",
+ "major",
+ "minor",
+ }
+}
+
+func (x *devTuple) beforeSave() {}
+
+func (x *devTuple) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.kind)
+ m.Save(1, &x.major)
+ m.Save(2, &x.minor)
+}
+
+func (x *devTuple) afterLoad() {}
+
+func (x *devTuple) StateLoad(m state.Source) {
+ m.Load(0, &x.kind)
+ m.Load(1, &x.major)
+ m.Load(2, &x.minor)
+}
+
func (x *registeredDevice) StateTypeName() string {
return "pkg/sentry/vfs.registeredDevice"
}
@@ -84,6 +192,114 @@ func (x *RegisterDeviceOptions) StateLoad(m state.Source) {
m.Load(0, &x.GroupName)
}
+func (x *EpollInstance) StateTypeName() string {
+ return "pkg/sentry/vfs.EpollInstance"
+}
+
+func (x *EpollInstance) StateFields() []string {
+ return []string{
+ "vfsfd",
+ "FileDescriptionDefaultImpl",
+ "DentryMetadataFileDescriptionImpl",
+ "NoLockFD",
+ "q",
+ "interest",
+ "ready",
+ }
+}
+
+func (x *EpollInstance) beforeSave() {}
+
+func (x *EpollInstance) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfsfd)
+ m.Save(1, &x.FileDescriptionDefaultImpl)
+ m.Save(2, &x.DentryMetadataFileDescriptionImpl)
+ m.Save(3, &x.NoLockFD)
+ m.Save(4, &x.q)
+ m.Save(5, &x.interest)
+ m.Save(6, &x.ready)
+}
+
+func (x *EpollInstance) afterLoad() {}
+
+func (x *EpollInstance) 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.q)
+ m.Load(5, &x.interest)
+ m.Load(6, &x.ready)
+}
+
+func (x *epollInterestKey) StateTypeName() string {
+ return "pkg/sentry/vfs.epollInterestKey"
+}
+
+func (x *epollInterestKey) StateFields() []string {
+ return []string{
+ "file",
+ "num",
+ }
+}
+
+func (x *epollInterestKey) beforeSave() {}
+
+func (x *epollInterestKey) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.file)
+ m.Save(1, &x.num)
+}
+
+func (x *epollInterestKey) afterLoad() {}
+
+func (x *epollInterestKey) StateLoad(m state.Source) {
+ m.Load(0, &x.file)
+ m.Load(1, &x.num)
+}
+
+func (x *epollInterest) StateTypeName() string {
+ return "pkg/sentry/vfs.epollInterest"
+}
+
+func (x *epollInterest) StateFields() []string {
+ return []string{
+ "epoll",
+ "key",
+ "waiter",
+ "mask",
+ "ready",
+ "epollInterestEntry",
+ "userData",
+ }
+}
+
+func (x *epollInterest) beforeSave() {}
+
+func (x *epollInterest) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.epoll)
+ m.Save(1, &x.key)
+ m.Save(2, &x.waiter)
+ m.Save(3, &x.mask)
+ m.Save(4, &x.ready)
+ m.Save(5, &x.epollInterestEntry)
+ m.Save(6, &x.userData)
+}
+
+func (x *epollInterest) afterLoad() {}
+
+func (x *epollInterest) StateLoad(m state.Source) {
+ m.Load(0, &x.epoll)
+ m.Load(1, &x.key)
+ m.Load(2, &x.waiter)
+ m.Load(3, &x.mask)
+ m.Load(4, &x.ready)
+ m.Load(5, &x.epollInterestEntry)
+ m.Load(6, &x.userData)
+}
+
func (x *epollInterestList) StateTypeName() string {
return "pkg/sentry/vfs.epollInterestList"
}
@@ -188,6 +404,275 @@ func (x *eventEntry) StateLoad(m state.Source) {
m.Load(1, &x.prev)
}
+func (x *FileDescription) StateTypeName() string {
+ return "pkg/sentry/vfs.FileDescription"
+}
+
+func (x *FileDescription) StateFields() []string {
+ return []string{
+ "FileDescriptionRefs",
+ "statusFlags",
+ "asyncHandler",
+ "epolls",
+ "vd",
+ "opts",
+ "readable",
+ "writable",
+ "usedLockBSD",
+ "impl",
+ }
+}
+
+func (x *FileDescription) beforeSave() {}
+
+func (x *FileDescription) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.FileDescriptionRefs)
+ m.Save(1, &x.statusFlags)
+ m.Save(2, &x.asyncHandler)
+ m.Save(3, &x.epolls)
+ m.Save(4, &x.vd)
+ m.Save(5, &x.opts)
+ m.Save(6, &x.readable)
+ m.Save(7, &x.writable)
+ m.Save(8, &x.usedLockBSD)
+ m.Save(9, &x.impl)
+}
+
+func (x *FileDescription) afterLoad() {}
+
+func (x *FileDescription) StateLoad(m state.Source) {
+ m.Load(0, &x.FileDescriptionRefs)
+ m.Load(1, &x.statusFlags)
+ m.Load(2, &x.asyncHandler)
+ m.Load(3, &x.epolls)
+ m.Load(4, &x.vd)
+ m.Load(5, &x.opts)
+ m.Load(6, &x.readable)
+ m.Load(7, &x.writable)
+ m.Load(8, &x.usedLockBSD)
+ m.Load(9, &x.impl)
+}
+
+func (x *FileDescriptionOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.FileDescriptionOptions"
+}
+
+func (x *FileDescriptionOptions) StateFields() []string {
+ return []string{
+ "AllowDirectIO",
+ "DenyPRead",
+ "DenyPWrite",
+ "UseDentryMetadata",
+ }
+}
+
+func (x *FileDescriptionOptions) beforeSave() {}
+
+func (x *FileDescriptionOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.AllowDirectIO)
+ m.Save(1, &x.DenyPRead)
+ m.Save(2, &x.DenyPWrite)
+ m.Save(3, &x.UseDentryMetadata)
+}
+
+func (x *FileDescriptionOptions) afterLoad() {}
+
+func (x *FileDescriptionOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.AllowDirectIO)
+ m.Load(1, &x.DenyPRead)
+ m.Load(2, &x.DenyPWrite)
+ m.Load(3, &x.UseDentryMetadata)
+}
+
+func (x *Dirent) StateTypeName() string {
+ return "pkg/sentry/vfs.Dirent"
+}
+
+func (x *Dirent) StateFields() []string {
+ return []string{
+ "Name",
+ "Type",
+ "Ino",
+ "NextOff",
+ }
+}
+
+func (x *Dirent) beforeSave() {}
+
+func (x *Dirent) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Name)
+ m.Save(1, &x.Type)
+ m.Save(2, &x.Ino)
+ m.Save(3, &x.NextOff)
+}
+
+func (x *Dirent) afterLoad() {}
+
+func (x *Dirent) StateLoad(m state.Source) {
+ m.Load(0, &x.Name)
+ m.Load(1, &x.Type)
+ m.Load(2, &x.Ino)
+ m.Load(3, &x.NextOff)
+}
+
+func (x *FileDescriptionDefaultImpl) StateTypeName() string {
+ return "pkg/sentry/vfs.FileDescriptionDefaultImpl"
+}
+
+func (x *FileDescriptionDefaultImpl) StateFields() []string {
+ return []string{}
+}
+
+func (x *FileDescriptionDefaultImpl) beforeSave() {}
+
+func (x *FileDescriptionDefaultImpl) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *FileDescriptionDefaultImpl) afterLoad() {}
+
+func (x *FileDescriptionDefaultImpl) StateLoad(m state.Source) {
+}
+
+func (x *DirectoryFileDescriptionDefaultImpl) StateTypeName() string {
+ return "pkg/sentry/vfs.DirectoryFileDescriptionDefaultImpl"
+}
+
+func (x *DirectoryFileDescriptionDefaultImpl) StateFields() []string {
+ return []string{}
+}
+
+func (x *DirectoryFileDescriptionDefaultImpl) beforeSave() {}
+
+func (x *DirectoryFileDescriptionDefaultImpl) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *DirectoryFileDescriptionDefaultImpl) afterLoad() {}
+
+func (x *DirectoryFileDescriptionDefaultImpl) StateLoad(m state.Source) {
+}
+
+func (x *DentryMetadataFileDescriptionImpl) StateTypeName() string {
+ return "pkg/sentry/vfs.DentryMetadataFileDescriptionImpl"
+}
+
+func (x *DentryMetadataFileDescriptionImpl) StateFields() []string {
+ return []string{}
+}
+
+func (x *DentryMetadataFileDescriptionImpl) beforeSave() {}
+
+func (x *DentryMetadataFileDescriptionImpl) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *DentryMetadataFileDescriptionImpl) afterLoad() {}
+
+func (x *DentryMetadataFileDescriptionImpl) StateLoad(m state.Source) {
+}
+
+func (x *StaticData) StateTypeName() string {
+ return "pkg/sentry/vfs.StaticData"
+}
+
+func (x *StaticData) StateFields() []string {
+ return []string{
+ "Data",
+ }
+}
+
+func (x *StaticData) beforeSave() {}
+
+func (x *StaticData) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Data)
+}
+
+func (x *StaticData) afterLoad() {}
+
+func (x *StaticData) StateLoad(m state.Source) {
+ m.Load(0, &x.Data)
+}
+
+func (x *DynamicBytesFileDescriptionImpl) StateTypeName() string {
+ return "pkg/sentry/vfs.DynamicBytesFileDescriptionImpl"
+}
+
+func (x *DynamicBytesFileDescriptionImpl) StateFields() []string {
+ return []string{
+ "data",
+ "buf",
+ "off",
+ "lastRead",
+ }
+}
+
+func (x *DynamicBytesFileDescriptionImpl) beforeSave() {}
+
+func (x *DynamicBytesFileDescriptionImpl) StateSave(m state.Sink) {
+ x.beforeSave()
+ var buf []byte = x.saveBuf()
+ m.SaveValue(1, buf)
+ m.Save(0, &x.data)
+ m.Save(2, &x.off)
+ m.Save(3, &x.lastRead)
+}
+
+func (x *DynamicBytesFileDescriptionImpl) afterLoad() {}
+
+func (x *DynamicBytesFileDescriptionImpl) StateLoad(m state.Source) {
+ m.Load(0, &x.data)
+ m.Load(2, &x.off)
+ m.Load(3, &x.lastRead)
+ m.LoadValue(1, new([]byte), func(y interface{}) { x.loadBuf(y.([]byte)) })
+}
+
+func (x *LockFD) StateTypeName() string {
+ return "pkg/sentry/vfs.LockFD"
+}
+
+func (x *LockFD) StateFields() []string {
+ return []string{
+ "locks",
+ }
+}
+
+func (x *LockFD) beforeSave() {}
+
+func (x *LockFD) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.locks)
+}
+
+func (x *LockFD) afterLoad() {}
+
+func (x *LockFD) StateLoad(m state.Source) {
+ m.Load(0, &x.locks)
+}
+
+func (x *NoLockFD) StateTypeName() string {
+ return "pkg/sentry/vfs.NoLockFD"
+}
+
+func (x *NoLockFD) StateFields() []string {
+ return []string{}
+}
+
+func (x *NoLockFD) beforeSave() {}
+
+func (x *NoLockFD) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *NoLockFD) afterLoad() {}
+
+func (x *NoLockFD) StateLoad(m state.Source) {
+}
+
func (x *FileDescriptionRefs) StateTypeName() string {
return "pkg/sentry/vfs.FileDescriptionRefs"
}
@@ -243,6 +728,63 @@ func (x *Filesystem) StateLoad(m state.Source) {
m.Load(3, &x.impl)
}
+func (x *PrependPathAtVFSRootError) StateTypeName() string {
+ return "pkg/sentry/vfs.PrependPathAtVFSRootError"
+}
+
+func (x *PrependPathAtVFSRootError) StateFields() []string {
+ return []string{}
+}
+
+func (x *PrependPathAtVFSRootError) beforeSave() {}
+
+func (x *PrependPathAtVFSRootError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *PrependPathAtVFSRootError) afterLoad() {}
+
+func (x *PrependPathAtVFSRootError) StateLoad(m state.Source) {
+}
+
+func (x *PrependPathAtNonMountRootError) StateTypeName() string {
+ return "pkg/sentry/vfs.PrependPathAtNonMountRootError"
+}
+
+func (x *PrependPathAtNonMountRootError) StateFields() []string {
+ return []string{}
+}
+
+func (x *PrependPathAtNonMountRootError) beforeSave() {}
+
+func (x *PrependPathAtNonMountRootError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *PrependPathAtNonMountRootError) afterLoad() {}
+
+func (x *PrependPathAtNonMountRootError) StateLoad(m state.Source) {
+}
+
+func (x *PrependPathSyntheticError) StateTypeName() string {
+ return "pkg/sentry/vfs.PrependPathSyntheticError"
+}
+
+func (x *PrependPathSyntheticError) StateFields() []string {
+ return []string{}
+}
+
+func (x *PrependPathSyntheticError) beforeSave() {}
+
+func (x *PrependPathSyntheticError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *PrependPathSyntheticError) afterLoad() {}
+
+func (x *PrependPathSyntheticError) StateLoad(m state.Source) {
+}
+
func (x *FilesystemRefs) StateTypeName() string {
return "pkg/sentry/vfs.FilesystemRefs"
}
@@ -292,6 +834,43 @@ func (x *registeredFilesystemType) StateLoad(m state.Source) {
m.Load(1, &x.opts)
}
+func (x *RegisterFilesystemTypeOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.RegisterFilesystemTypeOptions"
+}
+
+func (x *RegisterFilesystemTypeOptions) StateFields() []string {
+ return []string{
+ "AllowUserMount",
+ "AllowUserList",
+ "RequiresDevice",
+ }
+}
+
+func (x *RegisterFilesystemTypeOptions) beforeSave() {}
+
+func (x *RegisterFilesystemTypeOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.AllowUserMount)
+ m.Save(1, &x.AllowUserList)
+ m.Save(2, &x.RequiresDevice)
+}
+
+func (x *RegisterFilesystemTypeOptions) afterLoad() {}
+
+func (x *RegisterFilesystemTypeOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.AllowUserMount)
+ m.Load(1, &x.AllowUserList)
+ m.Load(2, &x.RequiresDevice)
+}
+
+func (x *EventType) StateTypeName() string {
+ return "pkg/sentry/vfs.EventType"
+}
+
+func (x *EventType) StateFields() []string {
+ return nil
+}
+
func (x *Inotify) StateTypeName() string {
return "pkg/sentry/vfs.Inotify"
}
@@ -435,6 +1014,32 @@ func (x *Event) StateLoad(m state.Source) {
m.Load(5, &x.name)
}
+func (x *FileLocks) StateTypeName() string {
+ return "pkg/sentry/vfs.FileLocks"
+}
+
+func (x *FileLocks) StateFields() []string {
+ return []string{
+ "bsd",
+ "posix",
+ }
+}
+
+func (x *FileLocks) beforeSave() {}
+
+func (x *FileLocks) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.bsd)
+ m.Save(1, &x.posix)
+}
+
+func (x *FileLocks) afterLoad() {}
+
+func (x *FileLocks) StateLoad(m state.Source) {
+ m.Load(0, &x.bsd)
+ m.Load(1, &x.posix)
+}
+
func (x *Mount) StateTypeName() string {
return "pkg/sentry/vfs.Mount"
}
@@ -459,12 +1064,13 @@ func (x *Mount) beforeSave() {}
func (x *Mount) StateSave(m state.Sink) {
x.beforeSave()
+ var key VirtualDentry = x.saveKey()
+ m.SaveValue(5, key)
m.Save(0, &x.vfs)
m.Save(1, &x.fs)
m.Save(2, &x.root)
m.Save(3, &x.ID)
m.Save(4, &x.Flags)
- m.Save(5, &x.key)
m.Save(6, &x.ns)
m.Save(7, &x.refs)
m.Save(8, &x.children)
@@ -480,12 +1086,12 @@ func (x *Mount) StateLoad(m state.Source) {
m.Load(2, &x.root)
m.Load(3, &x.ID)
m.Load(4, &x.Flags)
- m.Load(5, &x.key)
m.Load(6, &x.ns)
m.Load(7, &x.refs)
m.Load(8, &x.children)
m.Load(9, &x.umounted)
m.Load(10, &x.writers)
+ m.LoadValue(5, new(VirtualDentry), func(y interface{}) { x.loadKey(y.(VirtualDentry)) })
}
func (x *MountNamespace) StateTypeName() string {
@@ -520,6 +1126,32 @@ func (x *MountNamespace) StateLoad(m state.Source) {
m.Load(3, &x.mountpoints)
}
+func (x *umountRecursiveOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.umountRecursiveOptions"
+}
+
+func (x *umountRecursiveOptions) StateFields() []string {
+ return []string{
+ "eager",
+ "disconnectHierarchy",
+ }
+}
+
+func (x *umountRecursiveOptions) beforeSave() {}
+
+func (x *umountRecursiveOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.eager)
+ m.Save(1, &x.disconnectHierarchy)
+}
+
+func (x *umountRecursiveOptions) afterLoad() {}
+
+func (x *umountRecursiveOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.eager)
+ m.Load(1, &x.disconnectHierarchy)
+}
+
func (x *MountNamespaceRefs) StateTypeName() string {
return "pkg/sentry/vfs.MountNamespaceRefs"
}
@@ -543,6 +1175,544 @@ func (x *MountNamespaceRefs) StateLoad(m state.Source) {
m.Load(0, &x.refCount)
}
+func (x *GetDentryOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.GetDentryOptions"
+}
+
+func (x *GetDentryOptions) StateFields() []string {
+ return []string{
+ "CheckSearchable",
+ }
+}
+
+func (x *GetDentryOptions) beforeSave() {}
+
+func (x *GetDentryOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.CheckSearchable)
+}
+
+func (x *GetDentryOptions) afterLoad() {}
+
+func (x *GetDentryOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.CheckSearchable)
+}
+
+func (x *MkdirOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.MkdirOptions"
+}
+
+func (x *MkdirOptions) StateFields() []string {
+ return []string{
+ "Mode",
+ "ForSyntheticMountpoint",
+ }
+}
+
+func (x *MkdirOptions) beforeSave() {}
+
+func (x *MkdirOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Mode)
+ m.Save(1, &x.ForSyntheticMountpoint)
+}
+
+func (x *MkdirOptions) afterLoad() {}
+
+func (x *MkdirOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Mode)
+ m.Load(1, &x.ForSyntheticMountpoint)
+}
+
+func (x *MknodOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.MknodOptions"
+}
+
+func (x *MknodOptions) StateFields() []string {
+ return []string{
+ "Mode",
+ "DevMajor",
+ "DevMinor",
+ "Endpoint",
+ }
+}
+
+func (x *MknodOptions) beforeSave() {}
+
+func (x *MknodOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Mode)
+ m.Save(1, &x.DevMajor)
+ m.Save(2, &x.DevMinor)
+ m.Save(3, &x.Endpoint)
+}
+
+func (x *MknodOptions) afterLoad() {}
+
+func (x *MknodOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Mode)
+ m.Load(1, &x.DevMajor)
+ m.Load(2, &x.DevMinor)
+ m.Load(3, &x.Endpoint)
+}
+
+func (x *MountFlags) StateTypeName() string {
+ return "pkg/sentry/vfs.MountFlags"
+}
+
+func (x *MountFlags) StateFields() []string {
+ return []string{
+ "NoExec",
+ "NoATime",
+ "NoDev",
+ "NoSUID",
+ }
+}
+
+func (x *MountFlags) beforeSave() {}
+
+func (x *MountFlags) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.NoExec)
+ m.Save(1, &x.NoATime)
+ m.Save(2, &x.NoDev)
+ m.Save(3, &x.NoSUID)
+}
+
+func (x *MountFlags) afterLoad() {}
+
+func (x *MountFlags) StateLoad(m state.Source) {
+ m.Load(0, &x.NoExec)
+ m.Load(1, &x.NoATime)
+ m.Load(2, &x.NoDev)
+ m.Load(3, &x.NoSUID)
+}
+
+func (x *MountOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.MountOptions"
+}
+
+func (x *MountOptions) StateFields() []string {
+ return []string{
+ "Flags",
+ "ReadOnly",
+ "GetFilesystemOptions",
+ "InternalMount",
+ }
+}
+
+func (x *MountOptions) beforeSave() {}
+
+func (x *MountOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Flags)
+ m.Save(1, &x.ReadOnly)
+ m.Save(2, &x.GetFilesystemOptions)
+ m.Save(3, &x.InternalMount)
+}
+
+func (x *MountOptions) afterLoad() {}
+
+func (x *MountOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Flags)
+ m.Load(1, &x.ReadOnly)
+ m.Load(2, &x.GetFilesystemOptions)
+ m.Load(3, &x.InternalMount)
+}
+
+func (x *OpenOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.OpenOptions"
+}
+
+func (x *OpenOptions) StateFields() []string {
+ return []string{
+ "Flags",
+ "Mode",
+ "FileExec",
+ }
+}
+
+func (x *OpenOptions) beforeSave() {}
+
+func (x *OpenOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Flags)
+ m.Save(1, &x.Mode)
+ m.Save(2, &x.FileExec)
+}
+
+func (x *OpenOptions) afterLoad() {}
+
+func (x *OpenOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Flags)
+ m.Load(1, &x.Mode)
+ m.Load(2, &x.FileExec)
+}
+
+func (x *ReadOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.ReadOptions"
+}
+
+func (x *ReadOptions) StateFields() []string {
+ return []string{
+ "Flags",
+ }
+}
+
+func (x *ReadOptions) beforeSave() {}
+
+func (x *ReadOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Flags)
+}
+
+func (x *ReadOptions) afterLoad() {}
+
+func (x *ReadOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Flags)
+}
+
+func (x *RenameOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.RenameOptions"
+}
+
+func (x *RenameOptions) StateFields() []string {
+ return []string{
+ "Flags",
+ "MustBeDir",
+ }
+}
+
+func (x *RenameOptions) beforeSave() {}
+
+func (x *RenameOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Flags)
+ m.Save(1, &x.MustBeDir)
+}
+
+func (x *RenameOptions) afterLoad() {}
+
+func (x *RenameOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Flags)
+ m.Load(1, &x.MustBeDir)
+}
+
+func (x *SetStatOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.SetStatOptions"
+}
+
+func (x *SetStatOptions) StateFields() []string {
+ return []string{
+ "Stat",
+ "NeedWritePerm",
+ }
+}
+
+func (x *SetStatOptions) beforeSave() {}
+
+func (x *SetStatOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Stat)
+ m.Save(1, &x.NeedWritePerm)
+}
+
+func (x *SetStatOptions) afterLoad() {}
+
+func (x *SetStatOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Stat)
+ m.Load(1, &x.NeedWritePerm)
+}
+
+func (x *BoundEndpointOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.BoundEndpointOptions"
+}
+
+func (x *BoundEndpointOptions) StateFields() []string {
+ return []string{
+ "Addr",
+ }
+}
+
+func (x *BoundEndpointOptions) beforeSave() {}
+
+func (x *BoundEndpointOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Addr)
+}
+
+func (x *BoundEndpointOptions) afterLoad() {}
+
+func (x *BoundEndpointOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Addr)
+}
+
+func (x *GetXattrOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.GetXattrOptions"
+}
+
+func (x *GetXattrOptions) StateFields() []string {
+ return []string{
+ "Name",
+ "Size",
+ }
+}
+
+func (x *GetXattrOptions) beforeSave() {}
+
+func (x *GetXattrOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Name)
+ m.Save(1, &x.Size)
+}
+
+func (x *GetXattrOptions) afterLoad() {}
+
+func (x *GetXattrOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Name)
+ m.Load(1, &x.Size)
+}
+
+func (x *SetXattrOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.SetXattrOptions"
+}
+
+func (x *SetXattrOptions) StateFields() []string {
+ return []string{
+ "Name",
+ "Value",
+ "Flags",
+ }
+}
+
+func (x *SetXattrOptions) beforeSave() {}
+
+func (x *SetXattrOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Name)
+ m.Save(1, &x.Value)
+ m.Save(2, &x.Flags)
+}
+
+func (x *SetXattrOptions) afterLoad() {}
+
+func (x *SetXattrOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Name)
+ m.Load(1, &x.Value)
+ m.Load(2, &x.Flags)
+}
+
+func (x *StatOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.StatOptions"
+}
+
+func (x *StatOptions) StateFields() []string {
+ return []string{
+ "Mask",
+ "Sync",
+ }
+}
+
+func (x *StatOptions) beforeSave() {}
+
+func (x *StatOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Mask)
+ m.Save(1, &x.Sync)
+}
+
+func (x *StatOptions) afterLoad() {}
+
+func (x *StatOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Mask)
+ m.Load(1, &x.Sync)
+}
+
+func (x *UmountOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.UmountOptions"
+}
+
+func (x *UmountOptions) StateFields() []string {
+ return []string{
+ "Flags",
+ }
+}
+
+func (x *UmountOptions) beforeSave() {}
+
+func (x *UmountOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Flags)
+}
+
+func (x *UmountOptions) afterLoad() {}
+
+func (x *UmountOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Flags)
+}
+
+func (x *WriteOptions) StateTypeName() string {
+ return "pkg/sentry/vfs.WriteOptions"
+}
+
+func (x *WriteOptions) StateFields() []string {
+ return []string{
+ "Flags",
+ }
+}
+
+func (x *WriteOptions) beforeSave() {}
+
+func (x *WriteOptions) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Flags)
+}
+
+func (x *WriteOptions) afterLoad() {}
+
+func (x *WriteOptions) StateLoad(m state.Source) {
+ m.Load(0, &x.Flags)
+}
+
+func (x *AccessTypes) StateTypeName() string {
+ return "pkg/sentry/vfs.AccessTypes"
+}
+
+func (x *AccessTypes) StateFields() []string {
+ return nil
+}
+
+func (x *ResolvingPath) StateTypeName() string {
+ return "pkg/sentry/vfs.ResolvingPath"
+}
+
+func (x *ResolvingPath) StateFields() []string {
+ return []string{
+ "vfs",
+ "root",
+ "mount",
+ "start",
+ "pit",
+ "flags",
+ "mustBeDir",
+ "mustBeDirOrig",
+ "symlinks",
+ "symlinksOrig",
+ "curPart",
+ "numOrigParts",
+ "creds",
+ "nextMount",
+ "nextStart",
+ "absSymlinkTarget",
+ "parts",
+ "origParts",
+ }
+}
+
+func (x *ResolvingPath) beforeSave() {}
+
+func (x *ResolvingPath) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.vfs)
+ m.Save(1, &x.root)
+ m.Save(2, &x.mount)
+ m.Save(3, &x.start)
+ m.Save(4, &x.pit)
+ m.Save(5, &x.flags)
+ m.Save(6, &x.mustBeDir)
+ m.Save(7, &x.mustBeDirOrig)
+ m.Save(8, &x.symlinks)
+ m.Save(9, &x.symlinksOrig)
+ m.Save(10, &x.curPart)
+ m.Save(11, &x.numOrigParts)
+ m.Save(12, &x.creds)
+ m.Save(13, &x.nextMount)
+ m.Save(14, &x.nextStart)
+ m.Save(15, &x.absSymlinkTarget)
+ m.Save(16, &x.parts)
+ m.Save(17, &x.origParts)
+}
+
+func (x *ResolvingPath) afterLoad() {}
+
+func (x *ResolvingPath) StateLoad(m state.Source) {
+ m.Load(0, &x.vfs)
+ m.Load(1, &x.root)
+ m.Load(2, &x.mount)
+ m.Load(3, &x.start)
+ m.Load(4, &x.pit)
+ m.Load(5, &x.flags)
+ m.Load(6, &x.mustBeDir)
+ m.Load(7, &x.mustBeDirOrig)
+ m.Load(8, &x.symlinks)
+ m.Load(9, &x.symlinksOrig)
+ m.Load(10, &x.curPart)
+ m.Load(11, &x.numOrigParts)
+ m.Load(12, &x.creds)
+ m.Load(13, &x.nextMount)
+ m.Load(14, &x.nextStart)
+ m.Load(15, &x.absSymlinkTarget)
+ m.Load(16, &x.parts)
+ m.Load(17, &x.origParts)
+}
+
+func (x *resolveMountRootOrJumpError) StateTypeName() string {
+ return "pkg/sentry/vfs.resolveMountRootOrJumpError"
+}
+
+func (x *resolveMountRootOrJumpError) StateFields() []string {
+ return []string{}
+}
+
+func (x *resolveMountRootOrJumpError) beforeSave() {}
+
+func (x *resolveMountRootOrJumpError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *resolveMountRootOrJumpError) afterLoad() {}
+
+func (x *resolveMountRootOrJumpError) StateLoad(m state.Source) {
+}
+
+func (x *resolveMountPointError) StateTypeName() string {
+ return "pkg/sentry/vfs.resolveMountPointError"
+}
+
+func (x *resolveMountPointError) StateFields() []string {
+ return []string{}
+}
+
+func (x *resolveMountPointError) beforeSave() {}
+
+func (x *resolveMountPointError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *resolveMountPointError) afterLoad() {}
+
+func (x *resolveMountPointError) StateLoad(m state.Source) {
+}
+
+func (x *resolveAbsSymlinkError) StateTypeName() string {
+ return "pkg/sentry/vfs.resolveAbsSymlinkError"
+}
+
+func (x *resolveAbsSymlinkError) StateFields() []string {
+ return []string{}
+}
+
+func (x *resolveAbsSymlinkError) beforeSave() {}
+
+func (x *resolveAbsSymlinkError) StateSave(m state.Sink) {
+ x.beforeSave()
+}
+
+func (x *resolveAbsSymlinkError) afterLoad() {}
+
+func (x *resolveAbsSymlinkError) StateLoad(m state.Source) {
+}
+
func (x *VirtualFilesystem) StateTypeName() string {
return "pkg/sentry/vfs.VirtualFilesystem"
}
@@ -590,6 +1760,38 @@ func (x *VirtualFilesystem) StateLoad(m state.Source) {
m.Load(8, &x.filesystems)
}
+func (x *PathOperation) StateTypeName() string {
+ return "pkg/sentry/vfs.PathOperation"
+}
+
+func (x *PathOperation) StateFields() []string {
+ return []string{
+ "Root",
+ "Start",
+ "Path",
+ "FollowFinalSymlink",
+ }
+}
+
+func (x *PathOperation) beforeSave() {}
+
+func (x *PathOperation) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.Root)
+ m.Save(1, &x.Start)
+ m.Save(2, &x.Path)
+ m.Save(3, &x.FollowFinalSymlink)
+}
+
+func (x *PathOperation) afterLoad() {}
+
+func (x *PathOperation) StateLoad(m state.Source) {
+ m.Load(0, &x.Root)
+ m.Load(1, &x.Start)
+ m.Load(2, &x.Path)
+ m.Load(3, &x.FollowFinalSymlink)
+}
+
func (x *VirtualDentry) StateTypeName() string {
return "pkg/sentry/vfs.VirtualDentry"
}
@@ -617,24 +1819,70 @@ func (x *VirtualDentry) StateLoad(m state.Source) {
}
func init() {
+ state.Register((*anonFilesystemType)(nil))
+ state.Register((*anonFilesystem)(nil))
+ state.Register((*anonDentry)(nil))
state.Register((*Dentry)(nil))
+ state.Register((*DeviceKind)(nil))
+ state.Register((*devTuple)(nil))
state.Register((*registeredDevice)(nil))
state.Register((*RegisterDeviceOptions)(nil))
+ state.Register((*EpollInstance)(nil))
+ state.Register((*epollInterestKey)(nil))
+ state.Register((*epollInterest)(nil))
state.Register((*epollInterestList)(nil))
state.Register((*epollInterestEntry)(nil))
state.Register((*eventList)(nil))
state.Register((*eventEntry)(nil))
+ state.Register((*FileDescription)(nil))
+ state.Register((*FileDescriptionOptions)(nil))
+ state.Register((*Dirent)(nil))
+ state.Register((*FileDescriptionDefaultImpl)(nil))
+ state.Register((*DirectoryFileDescriptionDefaultImpl)(nil))
+ state.Register((*DentryMetadataFileDescriptionImpl)(nil))
+ state.Register((*StaticData)(nil))
+ state.Register((*DynamicBytesFileDescriptionImpl)(nil))
+ state.Register((*LockFD)(nil))
+ state.Register((*NoLockFD)(nil))
state.Register((*FileDescriptionRefs)(nil))
state.Register((*Filesystem)(nil))
+ state.Register((*PrependPathAtVFSRootError)(nil))
+ state.Register((*PrependPathAtNonMountRootError)(nil))
+ state.Register((*PrependPathSyntheticError)(nil))
state.Register((*FilesystemRefs)(nil))
state.Register((*registeredFilesystemType)(nil))
+ state.Register((*RegisterFilesystemTypeOptions)(nil))
+ state.Register((*EventType)(nil))
state.Register((*Inotify)(nil))
state.Register((*Watches)(nil))
state.Register((*Watch)(nil))
state.Register((*Event)(nil))
+ state.Register((*FileLocks)(nil))
state.Register((*Mount)(nil))
state.Register((*MountNamespace)(nil))
+ state.Register((*umountRecursiveOptions)(nil))
state.Register((*MountNamespaceRefs)(nil))
+ state.Register((*GetDentryOptions)(nil))
+ state.Register((*MkdirOptions)(nil))
+ state.Register((*MknodOptions)(nil))
+ state.Register((*MountFlags)(nil))
+ state.Register((*MountOptions)(nil))
+ state.Register((*OpenOptions)(nil))
+ state.Register((*ReadOptions)(nil))
+ state.Register((*RenameOptions)(nil))
+ state.Register((*SetStatOptions)(nil))
+ state.Register((*BoundEndpointOptions)(nil))
+ state.Register((*GetXattrOptions)(nil))
+ state.Register((*SetXattrOptions)(nil))
+ state.Register((*StatOptions)(nil))
+ state.Register((*UmountOptions)(nil))
+ state.Register((*WriteOptions)(nil))
+ state.Register((*AccessTypes)(nil))
+ state.Register((*ResolvingPath)(nil))
+ state.Register((*resolveMountRootOrJumpError)(nil))
+ state.Register((*resolveMountPointError)(nil))
+ state.Register((*resolveAbsSymlinkError)(nil))
state.Register((*VirtualFilesystem)(nil))
+ state.Register((*PathOperation)(nil))
state.Register((*VirtualDentry)(nil))
}
diff --git a/pkg/state/types.go b/pkg/state/types.go
index 215ef80f8..84aed8732 100644
--- a/pkg/state/types.go
+++ b/pkg/state/types.go
@@ -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
+ }
}