2020-01-27 18:04:07 +00:00
|
|
|
load("//tools:defs.bzl", "go_library", "go_test")
|
2018-04-27 17:37:02 +00:00
|
|
|
load("//tools/go_generics:defs.bzl", "go_template_instance")
|
|
|
|
|
2019-10-16 23:27:55 +00:00
|
|
|
package(licenses = ["notice"])
|
|
|
|
|
2018-04-27 17:37:02 +00:00
|
|
|
go_template_instance(
|
|
|
|
name = "dirty_set_impl",
|
|
|
|
out = "dirty_set_impl.go",
|
|
|
|
imports = {
|
2019-06-13 23:49:09 +00:00
|
|
|
"memmap": "gvisor.dev/gvisor/pkg/sentry/memmap",
|
|
|
|
"platform": "gvisor.dev/gvisor/pkg/sentry/platform",
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
package = "fsutil",
|
|
|
|
prefix = "Dirty",
|
|
|
|
template = "//pkg/segment:generic_set",
|
|
|
|
types = {
|
|
|
|
"Key": "uint64",
|
|
|
|
"Range": "memmap.MappableRange",
|
|
|
|
"Value": "DirtyInfo",
|
|
|
|
"Functions": "dirtySetFunctions",
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
go_template_instance(
|
|
|
|
name = "frame_ref_set_impl",
|
|
|
|
out = "frame_ref_set_impl.go",
|
|
|
|
imports = {
|
2019-06-13 23:49:09 +00:00
|
|
|
"platform": "gvisor.dev/gvisor/pkg/sentry/platform",
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
package = "fsutil",
|
VFS2 gofer client
Updates #1198
Opening host pipes (by spinning in fdpipe) and host sockets is not yet
complete, and will be done in a future CL.
Major differences from VFS1 gofer client (sentry/fs/gofer), with varying levels
of backportability:
- "Cache policies" are replaced by InteropMode, which control the behavior of
timestamps in addition to caching. Under InteropModeExclusive (analogous to
cacheAll) and InteropModeWritethrough (analogous to cacheAllWritethrough),
client timestamps are *not* written back to the server (it is not possible in
9P or Linux for clients to set ctime, so writing back client-authoritative
timestamps results in incoherence between atime/mtime and ctime). Under
InteropModeShared (analogous to cacheRemoteRevalidating), client timestamps
are not used at all (remote filesystem clocks are authoritative). cacheNone
is translated to InteropModeShared + new option
filesystemOptions.specialRegularFiles.
- Under InteropModeShared, "unstable attribute" reloading for permission
checks, lookup, and revalidation are fused, which is feasible in VFS2 since
gofer.filesystem controls path resolution. This results in a ~33% reduction
in RPCs for filesystem operations compared to cacheRemoteRevalidating. For
example, consider stat("/foo/bar/baz") where "/foo/bar/baz" fails
revalidation, resulting in the instantiation of a new dentry:
VFS1 RPCs:
getattr("/") // fs.MountNamespace.FindLink() => fs.Inode.CheckPermission() => gofer.inodeOperations.check() => gofer.inodeOperations.UnstableAttr()
walkgetattr("/", "foo") = fid1 // fs.Dirent.walk() => gofer.session.Revalidate() => gofer.cachePolicy.Revalidate()
clunk(fid1)
getattr("/foo") // CheckPermission
walkgetattr("/foo", "bar") = fid2 // Revalidate
clunk(fid2)
getattr("/foo/bar") // CheckPermission
walkgetattr("/foo/bar", "baz") = fid3 // Revalidate
clunk(fid3)
walkgetattr("/foo/bar", "baz") = fid4 // fs.Dirent.walk() => gofer.inodeOperations.Lookup
getattr("/foo/bar/baz") // linux.stat() => gofer.inodeOperations.UnstableAttr()
VFS2 RPCs:
getattr("/") // gofer.filesystem.walkExistingLocked()
walkgetattr("/", "foo") = fid1 // gofer.filesystem.stepExistingLocked()
clunk(fid1)
// No getattr: walkgetattr already updated metadata for permission check
walkgetattr("/foo", "bar") = fid2
clunk(fid2)
walkgetattr("/foo/bar", "baz") = fid3
// No clunk: fid3 used for new gofer.dentry
// No getattr: walkgetattr already updated metadata for stat()
- gofer.filesystem.unlinkAt() does not require instantiation of a dentry that
represents the file to be deleted. Updates #898.
- gofer.regularFileFD.OnClose() skips Tflushf for regular files under
InteropModeExclusive, as it's nonsensical to request a remote file flush
without flushing locally-buffered writes to that remote file first.
- Symlink targets are cached when InteropModeShared is not in effect.
- p9.QID.Path (which is already required to be unique for each file within a
server, and is accordingly already synthesized from device/inode numbers in
all known gofers) is used as-is for inode numbers, rather than being mapped
along with attr.RDev in the client to yet another synthetic inode number.
- Relevant parts of fsutil.CachingInodeOperations are inlined directly into
gofer package code. This avoids having to duplicate part of its functionality
in fsutil.HostMappable.
PiperOrigin-RevId: 293190213
2020-02-04 19:28:36 +00:00
|
|
|
prefix = "FrameRef",
|
2018-04-27 17:37:02 +00:00
|
|
|
template = "//pkg/segment:generic_set",
|
|
|
|
types = {
|
|
|
|
"Key": "uint64",
|
|
|
|
"Range": "platform.FileRange",
|
|
|
|
"Value": "uint64",
|
VFS2 gofer client
Updates #1198
Opening host pipes (by spinning in fdpipe) and host sockets is not yet
complete, and will be done in a future CL.
Major differences from VFS1 gofer client (sentry/fs/gofer), with varying levels
of backportability:
- "Cache policies" are replaced by InteropMode, which control the behavior of
timestamps in addition to caching. Under InteropModeExclusive (analogous to
cacheAll) and InteropModeWritethrough (analogous to cacheAllWritethrough),
client timestamps are *not* written back to the server (it is not possible in
9P or Linux for clients to set ctime, so writing back client-authoritative
timestamps results in incoherence between atime/mtime and ctime). Under
InteropModeShared (analogous to cacheRemoteRevalidating), client timestamps
are not used at all (remote filesystem clocks are authoritative). cacheNone
is translated to InteropModeShared + new option
filesystemOptions.specialRegularFiles.
- Under InteropModeShared, "unstable attribute" reloading for permission
checks, lookup, and revalidation are fused, which is feasible in VFS2 since
gofer.filesystem controls path resolution. This results in a ~33% reduction
in RPCs for filesystem operations compared to cacheRemoteRevalidating. For
example, consider stat("/foo/bar/baz") where "/foo/bar/baz" fails
revalidation, resulting in the instantiation of a new dentry:
VFS1 RPCs:
getattr("/") // fs.MountNamespace.FindLink() => fs.Inode.CheckPermission() => gofer.inodeOperations.check() => gofer.inodeOperations.UnstableAttr()
walkgetattr("/", "foo") = fid1 // fs.Dirent.walk() => gofer.session.Revalidate() => gofer.cachePolicy.Revalidate()
clunk(fid1)
getattr("/foo") // CheckPermission
walkgetattr("/foo", "bar") = fid2 // Revalidate
clunk(fid2)
getattr("/foo/bar") // CheckPermission
walkgetattr("/foo/bar", "baz") = fid3 // Revalidate
clunk(fid3)
walkgetattr("/foo/bar", "baz") = fid4 // fs.Dirent.walk() => gofer.inodeOperations.Lookup
getattr("/foo/bar/baz") // linux.stat() => gofer.inodeOperations.UnstableAttr()
VFS2 RPCs:
getattr("/") // gofer.filesystem.walkExistingLocked()
walkgetattr("/", "foo") = fid1 // gofer.filesystem.stepExistingLocked()
clunk(fid1)
// No getattr: walkgetattr already updated metadata for permission check
walkgetattr("/foo", "bar") = fid2
clunk(fid2)
walkgetattr("/foo/bar", "baz") = fid3
// No clunk: fid3 used for new gofer.dentry
// No getattr: walkgetattr already updated metadata for stat()
- gofer.filesystem.unlinkAt() does not require instantiation of a dentry that
represents the file to be deleted. Updates #898.
- gofer.regularFileFD.OnClose() skips Tflushf for regular files under
InteropModeExclusive, as it's nonsensical to request a remote file flush
without flushing locally-buffered writes to that remote file first.
- Symlink targets are cached when InteropModeShared is not in effect.
- p9.QID.Path (which is already required to be unique for each file within a
server, and is accordingly already synthesized from device/inode numbers in
all known gofers) is used as-is for inode numbers, rather than being mapped
along with attr.RDev in the client to yet another synthetic inode number.
- Relevant parts of fsutil.CachingInodeOperations are inlined directly into
gofer package code. This avoids having to duplicate part of its functionality
in fsutil.HostMappable.
PiperOrigin-RevId: 293190213
2020-02-04 19:28:36 +00:00
|
|
|
"Functions": "FrameRefSetFunctions",
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
go_template_instance(
|
|
|
|
name = "file_range_set_impl",
|
|
|
|
out = "file_range_set_impl.go",
|
|
|
|
imports = {
|
2019-06-13 23:49:09 +00:00
|
|
|
"memmap": "gvisor.dev/gvisor/pkg/sentry/memmap",
|
|
|
|
"platform": "gvisor.dev/gvisor/pkg/sentry/platform",
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
package = "fsutil",
|
|
|
|
prefix = "FileRange",
|
|
|
|
template = "//pkg/segment:generic_set",
|
|
|
|
types = {
|
|
|
|
"Key": "uint64",
|
|
|
|
"Range": "memmap.MappableRange",
|
|
|
|
"Value": "uint64",
|
2020-01-06 20:51:35 +00:00
|
|
|
"Functions": "FileRangeSetFunctions",
|
2018-04-27 17:37:02 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
go_library(
|
|
|
|
name = "fsutil",
|
|
|
|
srcs = [
|
|
|
|
"dirty_set.go",
|
|
|
|
"dirty_set_impl.go",
|
|
|
|
"file.go",
|
|
|
|
"file_range_set.go",
|
|
|
|
"file_range_set_impl.go",
|
|
|
|
"frame_ref_set.go",
|
|
|
|
"frame_ref_set_impl.go",
|
|
|
|
"fsutil.go",
|
|
|
|
"host_file_mapper.go",
|
|
|
|
"host_file_mapper_state.go",
|
|
|
|
"host_file_mapper_unsafe.go",
|
2019-01-26 01:22:04 +00:00
|
|
|
"host_mappable.go",
|
2018-04-27 17:37:02 +00:00
|
|
|
"inode.go",
|
|
|
|
"inode_cached.go",
|
|
|
|
],
|
|
|
|
visibility = ["//pkg/sentry:internal"],
|
|
|
|
deps = [
|
|
|
|
"//pkg/abi/linux",
|
2020-01-27 23:17:58 +00:00
|
|
|
"//pkg/context",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/log",
|
2020-01-27 23:17:58 +00:00
|
|
|
"//pkg/safemem",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/sentry/arch",
|
|
|
|
"//pkg/sentry/device",
|
|
|
|
"//pkg/sentry/fs",
|
|
|
|
"//pkg/sentry/kernel/time",
|
|
|
|
"//pkg/sentry/memmap",
|
2019-03-14 15:11:36 +00:00
|
|
|
"//pkg/sentry/pgalloc",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/sentry/platform",
|
2018-10-17 18:36:32 +00:00
|
|
|
"//pkg/sentry/socket/unix/transport",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/sentry/usage",
|
|
|
|
"//pkg/state",
|
2020-01-10 06:00:42 +00:00
|
|
|
"//pkg/sync",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/syserror",
|
2020-01-27 23:17:58 +00:00
|
|
|
"//pkg/usermem",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/waiter",
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
go_test(
|
|
|
|
name = "fsutil_test",
|
|
|
|
size = "small",
|
|
|
|
srcs = [
|
|
|
|
"dirty_set_test.go",
|
|
|
|
"inode_cached_test.go",
|
|
|
|
],
|
2020-01-27 18:04:07 +00:00
|
|
|
library = ":fsutil",
|
2018-04-27 17:37:02 +00:00
|
|
|
deps = [
|
2020-01-27 23:17:58 +00:00
|
|
|
"//pkg/context",
|
|
|
|
"//pkg/safemem",
|
|
|
|
"//pkg/sentry/contexttest",
|
2018-04-27 17:37:02 +00:00
|
|
|
"//pkg/sentry/fs",
|
|
|
|
"//pkg/sentry/kernel/time",
|
|
|
|
"//pkg/sentry/memmap",
|
2019-05-09 22:34:44 +00:00
|
|
|
"//pkg/syserror",
|
2020-01-27 23:17:58 +00:00
|
|
|
"//pkg/usermem",
|
2018-04-27 17:37:02 +00:00
|
|
|
],
|
|
|
|
)
|