vfs

package
v0.0.0-...-522126a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 23, 2019 License: Apache-2.0 Imports: 20 Imported by: 0

README

The gVisor Virtual Filesystem

THIS PACKAGE IS CURRENTLY EXPERIMENTAL AND NOT READY OR ENABLED FOR PRODUCTION USE. For the filesystem implementation currently used by gVisor, see the fs package.

Implementation Notes

Reference Counting

Filesystem, Dentry, Mount, MountNamespace, and FileDescription are all reference-counted. Mount and MountNamespace are exclusively VFS-managed; when their reference count reaches zero, VFS releases their resources. Filesystem and FileDescription management is shared between VFS and filesystem implementations; when their reference count reaches zero, VFS notifies the implementation by calling FilesystemImpl.Release() or FileDescriptionImpl.Release() respectively and then releases VFS-owned resources. Dentries are exclusively managed by filesystem implementations; reference count changes are abstracted through DentryImpl, which should release resources when reference count reaches zero.

Filesystem references are held by:

  • Mount: Each referenced Mount holds a reference on the mounted Filesystem.

Dentry references are held by:

  • FileDescription: Each referenced FileDescription holds a reference on the Dentry through which it was opened, via FileDescription.vd.dentry.

  • Mount: Each referenced Mount holds a reference on its mount point and on the mounted filesystem root. The mount point is mutable (mount(MS_MOVE)).

Mount references are held by:

  • FileDescription: Each referenced FileDescription holds a reference on the Mount on which it was opened, via FileDescription.vd.mount.

  • Mount: Each referenced Mount holds a reference on its parent, which is the mount containing its mount point.

  • VirtualFilesystem: A reference is held on each Mount that has not been umounted.

MountNamespace and FileDescription references are held by users of VFS. The expectation is that each kernel.Task holds a reference on its corresponding MountNamespace, and each file descriptor holds a reference on its represented FileDescription.

Notes:

  • Dentries do not hold a reference on their owning Filesystem. Instead, all uses of a Dentry occur in the context of a Mount, which holds a reference on the relevant Filesystem (see e.g. the VirtualDentry type). As a corollary, when releasing references on both a Dentry and its corresponding Mount, the Dentry's reference must be released first (because releasing the Mount's reference may release the last reference on the Filesystem, whose state may be required to release the Dentry reference).
The Inheritance Pattern

Filesystem, Dentry, and FileDescription are all concepts featuring both state that must be shared between VFS and filesystem implementations, and operations that are implementation-defined. To facilitate this, each of these three concepts follows the same pattern, shown below for Dentry:

// Dentry represents a node in a filesystem tree.
type Dentry struct {
  // VFS-required dentry state.
  parent *Dentry
  // ...

  // impl is the DentryImpl associated with this Dentry. impl is immutable.
  // This should be the last field in Dentry.
  impl DentryImpl
}

// Init must be called before first use of d.
func (d *Dentry) Init(impl DentryImpl) {
  d.impl = impl
}

// Impl returns the DentryImpl associated with d.
func (d *Dentry) Impl() DentryImpl {
  return d.impl
}

// DentryImpl contains implementation-specific details of a Dentry.
// Implementations of DentryImpl should contain their associated Dentry by
// value as their first field.
type DentryImpl interface {
  // VFS-required implementation-defined dentry operations.
  IncRef()
  // ...
}

This construction, which is essentially a type-safe analogue to Linux's container_of pattern, has the following properties:

  • VFS works almost exclusively with pointers to Dentry rather than DentryImpl interface objects, such as in the type of Dentry.parent. This avoids interface method calls (which are somewhat expensive to perform, and defeat inlining and escape analysis), reduces the size of VFS types (since an interface object is two pointers in size), and allows pointers to be loaded and stored atomically using sync/atomic. Implementation-defined behavior is accessed via Dentry.impl when required.

  • Filesystem implementations can access the implementation-defined state associated with objects of VFS types by type-asserting or type-switching (e.g. Dentry.Impl().(*myDentry)). Type assertions to a concrete type require only an equality comparison of the interface object's type pointer to a static constant, and are consequently very fast.

  • Filesystem implementations can access the VFS state associated with objects of implementation-defined types directly.

  • VFS and implementation-defined state for a given type occupy the same object, minimizing memory allocations and maximizing memory locality. impl is the last field in Dentry, and Dentry is the first field in DentryImpl implementations, for similar reasons: this tends to cause fetching of the Dentry.impl interface object to also fetch DentryImpl fields, either because they are in the same cache line or via next-line prefetching.

Future Work

  • Most mount(2) features, and unmounting, are incomplete.

  • VFS1 filesystems are not directly compatible with VFS2. It may be possible to implement shims that implement vfs.FilesystemImpl for fs.MountNamespace, vfs.DentryImpl for fs.Dirent, and vfs.FileDescriptionImpl for fs.File, which may be adequate for filesystems that are not performance-critical (e.g. sysfs); however, it is not clear that this will be less effort than simply porting the filesystems in question. Practically speaking, the following filesystems will probably need to be ported or made compatible through a shim to evaluate filesystem performance on realistic workloads:

    • devfs/procfs/sysfs, which will realistically be necessary to execute most applications. (Note that procfs and sysfs do not support hard links, so they do not require the complexity of separate inode objects. Also note that Linux's /dev is actually a variant of tmpfs called devtmpfs.)

    • tmpfs. This should be relatively straightforward: copy/paste memfs, store regular file contents in pgalloc-allocated memory instead of []byte, and add support for file timestamps. (In fact, it probably makes more sense to convert memfs to tmpfs and not keep the former.)

    • A remote filesystem, either lisafs (if it is ready by the time that other benchmarking prerequisites are) or v9fs (aka 9P, aka gofers).

    • epoll files.

    Filesystems that will need to be ported before switching to VFS2, but can probably be skipped for early testing:

    • overlayfs, which is needed for (at least) synthetic mount points.

    • Support for host ttys.

    • timerfd files.

    Filesystems that can be probably dropped:

    • ashmem, which is far too incomplete to use.

    • binder, which is similarly far too incomplete to use.

    • whitelistfs, which we are already actively attempting to remove.

  • Save/restore. For instance, it is unclear if the current implementation of the state package supports the inheritance pattern described above.

  • Many features that were previously implemented by VFS must now be implemented by individual filesystems (though, in most cases, this should consist of calls to hooks or libraries provided by vfs or other packages). This includes, but is not necessarily limited to:

    • Block and character device special files

    • Inotify

    • File locking

    • O_ASYNC

  • Reference counts in the vfs package do not use the refs package since refs.AtomicRefCount adds 64 bytes of overhead to each 8-byte reference count, resulting in considerable cache bloat. 24 bytes of this overhead is for weak reference support, which have poor performance and will not be used by VFS2. The remaining 40 bytes is to store a descriptive string and stack trace for reference leak checking; we can support reference leak checking without incurring this space overhead by including the applicable information directly in finalizers for applicable types.

Documentation

Overview

Package vfs implements a virtual filesystem layer.

Lock order:

FilesystemImpl/FileDescriptionImpl locks

VirtualFilesystem.mountMu
  Dentry.mu
    Locks acquired by FilesystemImpls between Prepare{Delete,Rename}Dentry and Commit{Delete,Rename*}Dentry
  VirtualFilesystem.filesystemsMu

VirtualFilesystem.fsTypesMu

Locking Dentry.mu in multiple Dentries requires holding VirtualFilesystem.mountMu.

Index

Constants

View Source
const (
	// CtxMountNamespace is a Context.Value key for a MountNamespace.
	CtxMountNamespace contextID = iota

	// CtxRoot is a Context.Value key for a VFS root.
	CtxRoot
)
View Source
const (
	MayRead  AccessTypes = 4
	MayWrite             = 2
	MayExec              = 1
)

Bits in AccessTypes.

Variables

This section is empty.

Functions

func CanActAsOwner

func CanActAsOwner(creds *auth.Credentials, kuid auth.KUID) bool

CanActAsOwner returns true if creds can act as the owner of a file with the given owning UID, consistent with Linux's fs/inode.c:inode_owner_or_capable().

func CheckSetStat

func CheckSetStat(creds *auth.Credentials, stat *linux.Statx, mode uint16, kuid auth.KUID, kgid auth.KGID) error

CheckSetStat checks that creds has permission to change the metadata of a file with the given permissions, UID, and GID as specified by stat, subject to the rules of Linux's fs/attr.c:setattr_prepare().

func GenericCheckPermissions

func GenericCheckPermissions(creds *auth.Credentials, ats AccessTypes, isDir bool, mode uint16, kuid auth.KUID, kgid auth.KGID) error

GenericCheckPermissions checks that creds has the given access rights on a file with the given permissions, UID, and GID, subject to the rules of fs/namei.c:generic_permission(). isDir is true if the file is a directory.

func GenericConfigureMMap

func GenericConfigureMMap(fd *FileDescription, m memmap.Mappable, opts *memmap.MMapOpts) error

GenericConfigureMMap may be used by most implementations of FileDescriptionImpl.ConfigureMMap.

func GenericParseMountOptions

func GenericParseMountOptions(str string) map[string]string

GenericParseMountOptions parses a comma-separated list of options of the form "key" or "key=value", where neither key nor value contain commas, and returns it as a map. If str contains duplicate keys, then the last value wins. For example:

str = "key0=value0,key1,key2=value2,key0=value3" -> map{'key0':'value3','key1':”,'key2':'value2'}

GenericParseMountOptions is not appropriate if values may contain commas, e.g. in the case of the mpol mount option for tmpfs(5).

func GenericPrependPath

func GenericPrependPath(vfsroot, vd VirtualDentry, b *fspath.Builder) error

GenericPrependPath may be used by implementations of FilesystemImpl.PrependPath() for which a single statically-determined lock or set of locks is sufficient to ensure its preconditions (as opposed to e.g. per-Dentry locks).

Preconditions: Dentry.Name() and Dentry.Parent() must be held constant for vd.Dentry() and all of its ancestors.

func HasCapabilityOnFile

func HasCapabilityOnFile(creds *auth.Credentials, cp linux.Capability, kuid auth.KUID, kgid auth.KGID) bool

HasCapabilityOnFile returns true if creds has the given capability with respect to a file with the given owning UID and GID, consistent with Linux's kernel/capability.c:capable_wrt_inode_uidgid().

func MayReadFileWithOpenFlags

func MayReadFileWithOpenFlags(flags uint32) bool

MayReadFileWithOpenFlags returns true if a file with the given open flags should be readable.

func MayWriteFileWithOpenFlags

func MayWriteFileWithOpenFlags(flags uint32) bool

MayWriteFileWithOpenFlags returns true if a file with the given open flags should be writable.

Types

type AccessTypes

type AccessTypes uint16

AccessTypes is a bitmask of Unix file permissions.

func AccessTypesForOpenFlags

func AccessTypesForOpenFlags(flags uint32) AccessTypes

AccessTypesForOpenFlags returns the access types required to open a file with the given OpenOptions.Flags. Note that this is NOT the same thing as the set of accesses permitted for the opened file:

- O_TRUNC causes MayWrite to be set in the returned AccessTypes (since it mutates the file), but does not permit the opened to write to the file thereafter.

- "Linux reserves the special, nonstandard access mode 3 (binary 11) in flags to mean: check for read and write permission on the file and return a file descriptor that can't be used for reading or writing." - open(2). Thus AccessTypesForOpenFlags returns MayRead|MayWrite in this case, but filesystems are responsible for ensuring that access is denied.

Use May{Read,Write}FileWithOpenFlags() for these checks instead.

type Dentry

type Dentry struct {
	// contains filtered or unexported fields
}

Dentry represents a node in a Filesystem tree which may represent a file.

Dentries are reference-counted. Unless otherwise specified, all Dentry methods require that a reference is held.

A Dentry transitions through up to 3 different states through its lifetime:

- Dentries are initially "independent". Independent Dentries have no parent, and consequently no name.

- Dentry.InsertChild() causes an independent Dentry to become a "child" of another Dentry. A child node has a parent node, and a name in that parent, both of which are mutable by DentryMoveChild(). Each child Dentry's name is unique within its parent.

- Dentry.RemoveChild() causes a child Dentry to become "disowned". A disowned Dentry can still refer to its former parent and its former name in said parent, but the disowned Dentry is no longer reachable from its parent, and a new Dentry with the same name may become a child of the parent. (This is analogous to a struct dentry being "unhashed" in Linux.)

Dentry is loosely analogous to Linux's struct dentry, but:

- VFS does not associate Dentries with inodes. gVisor interacts primarily with filesystems that are accessed through filesystem APIs (as opposed to raw block devices); many such APIs support only paths and file descriptors, and not inodes. Furthermore, when parties outside the scope of VFS can rename inodes on such filesystems, VFS generally cannot "follow" the rename, both due to synchronization issues and because it may not even be able to name the destination path; this implies that it would in fact be incorrect for Dentries to be associated with inodes on such filesystems. Consequently, operations that are inode operations in Linux are FilesystemImpl methods and/or FileDescriptionImpl methods in gVisor's VFS. Filesystems that do support inodes may store appropriate state in implementations of DentryImpl.

- VFS does not provide synchronization for mutable Dentry fields, other than mount-related ones.

- VFS does not require that Dentries are instantiated for all paths accessed through VFS, only those that are tracked beyond the scope of a single Filesystem operation. This includes file descriptions, mount points, mount roots, process working directories, and chroots. This avoids instantiation of Dentries for operations on mutable remote filesystems that can't actually cache any state in the Dentry.

- For the reasons above, VFS is not directly responsible for managing Dentry lifetime. Dentry reference counts only indicate the extent to which VFS requires Dentries to exist; Filesystems may elect to cache or discard Dentries with zero references.

func (*Dentry) Child

func (d *Dentry) Child(name string) *Dentry

Child returns d's child with the given name in its owning Filesystem. It does not take a reference on the returned Dentry. If no such child exists, Child returns nil.

func (*Dentry) Children

func (d *Dentry) Children() map[string]*Dentry

Children returns a map containing all of d's children.

func (*Dentry) DecRef

func (d *Dentry) DecRef()

DecRef decrements d's reference count.

func (*Dentry) HasChildren

func (d *Dentry) HasChildren() bool

HasChildren returns true if d has any children.

func (*Dentry) Impl

func (d *Dentry) Impl() DentryImpl

Impl returns the DentryImpl associated with d.

func (*Dentry) IncRef

func (d *Dentry) IncRef()

IncRef increments d's reference count.

func (*Dentry) Init

func (d *Dentry) Init(impl DentryImpl)

Init must be called before first use of d.

func (*Dentry) InsertChild

func (d *Dentry) InsertChild(child *Dentry, name string)

InsertChild makes child a child of d with the given name.

InsertChild is a mutator of d and child.

Preconditions: child must be an independent Dentry. d and child must be from the same Filesystem. d must not already have a child with the given name.

func (*Dentry) IsDisowned

func (d *Dentry) IsDisowned() bool

IsDisowned returns true if d is disowned.

func (*Dentry) Name

func (d *Dentry) Name() string

Name returns d's name in its parent in its owning Filesystem. If d is independent, Name returns an empty string.

func (*Dentry) Parent

func (d *Dentry) Parent() *Dentry

Parent returns d's parent in its owning Filesystem. It does not take a reference on the returned Dentry. If d is independent, Parent returns nil.

func (*Dentry) ParentOrSelf

func (d *Dentry) ParentOrSelf() *Dentry

ParentOrSelf is equivalent to Parent, but returns d if d is independent.

func (*Dentry) TryIncRef

func (d *Dentry) TryIncRef() bool

TryIncRef increments d's reference count and returns true. If d's reference count is zero, TryIncRef may instead do nothing and return false.

type DentryImpl

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.
	IncRef()

	// TryIncRef increments the Dentry's reference count and returns true. If
	// the Dentry's reference count is zero, TryIncRef may do nothing and
	// return false. (It is also permitted to succeed if it can restore the
	// guarantee that the Dentry is coherent with the state of the filesystem.)
	//
	// TryIncRef does not require that a reference is held on the Dentry.
	TryIncRef() bool

	// DecRef decrements the Dentry's reference count.
	DecRef()
}

DentryImpl contains implementation details for a Dentry. Implementations of DentryImpl should contain their associated Dentry by value as their first field.

type DirectoryFileDescriptionDefaultImpl

type DirectoryFileDescriptionDefaultImpl struct{}

DirectoryFileDescriptionDefaultImpl may be embedded by implementations of FileDescriptionImpl that always represent directories to obtain implementations of non-directory I/O methods that return EISDIR.

func (DirectoryFileDescriptionDefaultImpl) PRead

PRead implements FileDescriptionImpl.PRead.

func (DirectoryFileDescriptionDefaultImpl) PWrite

PWrite implements FileDescriptionImpl.PWrite.

func (DirectoryFileDescriptionDefaultImpl) Read

Read implements FileDescriptionImpl.Read.

func (DirectoryFileDescriptionDefaultImpl) Write

Write implements FileDescriptionImpl.Write.

type Dirent

type Dirent struct {
	// Name is the filename.
	Name string

	// Type is the file type, a linux.DT_* constant.
	Type uint8

	// Ino is the inode number.
	Ino uint64

	// NextOff is the offset of the *next* Dirent in the directory; that is,
	// FileDescription.Seek(NextOff, SEEK_SET) (as called by seekdir(3)) will
	// cause the next call to FileDescription.IterDirents() to yield the next
	// Dirent. (The offset of the first Dirent in a directory is always 0.)
	NextOff int64
}

Dirent holds the information contained in struct linux_dirent64.

type DynamicBytesFileDescriptionImpl

type DynamicBytesFileDescriptionImpl struct {
	// contains filtered or unexported fields
}

DynamicBytesFileDescriptionImpl may be embedded by implementations of FileDescriptionImpl that represent read-only regular files whose contents are backed by a bytes.Buffer that is regenerated when necessary, consistent with Linux's fs/seq_file.c:single_open().

DynamicBytesFileDescriptionImpl.SetDataSource() must be called before first use.

func (*DynamicBytesFileDescriptionImpl) PRead

PRead implements FileDescriptionImpl.PRead.

func (*DynamicBytesFileDescriptionImpl) Read

Read implements FileDescriptionImpl.Read.

func (*DynamicBytesFileDescriptionImpl) Seek

func (fd *DynamicBytesFileDescriptionImpl) Seek(ctx context.Context, offset int64, whence int32) (int64, error)

Seek implements FileDescriptionImpl.Seek.

func (*DynamicBytesFileDescriptionImpl) SetDataSource

func (fd *DynamicBytesFileDescriptionImpl) SetDataSource(data DynamicBytesSource)

SetDataSource must be called exactly once on fd before first use.

type DynamicBytesSource

type DynamicBytesSource interface {
	// Generate writes the file's contents to buf.
	Generate(ctx context.Context, buf *bytes.Buffer) error
}

DynamicBytesSource represents a data source for a DynamicBytesFileDescriptionImpl.

type FDTestFilesystem

type FDTestFilesystem struct {
	// contains filtered or unexported fields
}

FDTestFilesystem is a test-only FilesystemImpl produced by FDTestFilesystemType.

func (*FDTestFilesystem) GetDentryAt

func (fs *FDTestFilesystem) GetDentryAt(ctx context.Context, rp *ResolvingPath, opts GetDentryOptions) (*Dentry, error)

GetDentryAt implements FilesystemImpl.GetDentryAt.

func (*FDTestFilesystem) GetxattrAt

func (fs *FDTestFilesystem) GetxattrAt(ctx context.Context, rp *ResolvingPath, name string) (string, error)

GetxattrAt implements FilesystemImpl.GetxattrAt.

func (*FDTestFilesystem) LinkAt

LinkAt implements FilesystemImpl.LinkAt.

func (*FDTestFilesystem) ListxattrAt

func (fs *FDTestFilesystem) ListxattrAt(ctx context.Context, rp *ResolvingPath) ([]string, error)

ListxattrAt implements FilesystemImpl.ListxattrAt.

func (*FDTestFilesystem) MkdirAt

func (fs *FDTestFilesystem) MkdirAt(ctx context.Context, rp *ResolvingPath, opts MkdirOptions) error

MkdirAt implements FilesystemImpl.MkdirAt.

func (*FDTestFilesystem) MknodAt

func (fs *FDTestFilesystem) MknodAt(ctx context.Context, rp *ResolvingPath, opts MknodOptions) error

MknodAt implements FilesystemImpl.MknodAt.

func (*FDTestFilesystem) NewDentry

func (fs *FDTestFilesystem) NewDentry() *Dentry

NewDentry returns a new Dentry.

func (*FDTestFilesystem) OpenAt

OpenAt implements FilesystemImpl.OpenAt.

func (*FDTestFilesystem) PrependPath

func (fs *FDTestFilesystem) PrependPath(ctx context.Context, vfsroot, vd VirtualDentry, b *fspath.Builder) error

PrependPath implements FilesystemImpl.PrependPath.

func (*FDTestFilesystem) ReadlinkAt

func (fs *FDTestFilesystem) ReadlinkAt(ctx context.Context, rp *ResolvingPath) (string, error)

ReadlinkAt implements FilesystemImpl.ReadlinkAt.

func (*FDTestFilesystem) Release

func (fs *FDTestFilesystem) Release()

Release implements FilesystemImpl.Release.

func (*FDTestFilesystem) RemovexattrAt

func (fs *FDTestFilesystem) RemovexattrAt(ctx context.Context, rp *ResolvingPath, name string) error

RemovexattrAt implements FilesystemImpl.RemovexattrAt.

func (*FDTestFilesystem) RenameAt

RenameAt implements FilesystemImpl.RenameAt.

func (*FDTestFilesystem) RmdirAt

func (fs *FDTestFilesystem) RmdirAt(ctx context.Context, rp *ResolvingPath) error

RmdirAt implements FilesystemImpl.RmdirAt.

func (*FDTestFilesystem) SetStatAt

func (fs *FDTestFilesystem) SetStatAt(ctx context.Context, rp *ResolvingPath, opts SetStatOptions) error

SetStatAt implements FilesystemImpl.SetStatAt.

func (*FDTestFilesystem) SetxattrAt

func (fs *FDTestFilesystem) SetxattrAt(ctx context.Context, rp *ResolvingPath, opts SetxattrOptions) error

SetxattrAt implements FilesystemImpl.SetxattrAt.

func (*FDTestFilesystem) StatAt

func (fs *FDTestFilesystem) StatAt(ctx context.Context, rp *ResolvingPath, opts StatOptions) (linux.Statx, error)

StatAt implements FilesystemImpl.StatAt.

func (*FDTestFilesystem) StatFSAt

func (fs *FDTestFilesystem) StatFSAt(ctx context.Context, rp *ResolvingPath) (linux.Statfs, error)

StatFSAt implements FilesystemImpl.StatFSAt.

func (*FDTestFilesystem) SymlinkAt

func (fs *FDTestFilesystem) SymlinkAt(ctx context.Context, rp *ResolvingPath, target string) error

SymlinkAt implements FilesystemImpl.SymlinkAt.

func (*FDTestFilesystem) Sync

func (fs *FDTestFilesystem) Sync(ctx context.Context) error

Sync implements FilesystemImpl.Sync.

func (*FDTestFilesystem) UnlinkAt

func (fs *FDTestFilesystem) UnlinkAt(ctx context.Context, rp *ResolvingPath) error

UnlinkAt implements FilesystemImpl.UnlinkAt.

type FDTestFilesystemType

type FDTestFilesystemType struct{}

FDTestFilesystemType is a test-only FilesystemType that produces Filesystems for which all FilesystemImpl methods taking a path return EPERM. It is used to produce Mounts and Dentries for testing of FileDescriptionImpls that do not depend on their originating Filesystem.

func (FDTestFilesystemType) GetFilesystem

func (fstype FDTestFilesystemType) GetFilesystem(ctx context.Context, vfsObj *VirtualFilesystem, creds *auth.Credentials, source string, opts GetFilesystemOptions) (*Filesystem, *Dentry, error)

GetFilesystem implements FilesystemType.GetFilesystem.

type FileDescription

type FileDescription struct {
	// contains filtered or unexported fields
}

A FileDescription represents an open file description, which is the entity referred to by a file descriptor (POSIX.1-2017 3.258 "Open File Description").

FileDescriptions are reference-counted. Unless otherwise specified, all FileDescription methods require that a reference is held.

FileDescription is analogous to Linux's struct file.

func (*FileDescription) ConfigureMMap

func (fd *FileDescription) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error

ConfigureMMap mutates opts to implement mmap(2) for the file represented by fd.

func (*FileDescription) DecRef

func (fd *FileDescription) DecRef()

DecRef decrements fd's reference count.

func (*FileDescription) Dentry

func (fd *FileDescription) Dentry() *Dentry

Dentry returns the dentry at which fd was opened. It does not take a reference on the returned Dentry.

func (*FileDescription) DeviceID

func (fd *FileDescription) DeviceID() uint64

DeviceID implements memmap.MappingIdentity.DeviceID.

func (*FileDescription) Getxattr

func (fd *FileDescription) Getxattr(ctx context.Context, name string) (string, error)

Getxattr returns the value associated with the given extended attribute for the file represented by fd.

func (*FileDescription) Impl

Impl returns the FileDescriptionImpl associated with fd.

func (*FileDescription) IncRef

func (fd *FileDescription) IncRef()

IncRef increments fd's reference count.

func (*FileDescription) Init

func (fd *FileDescription) Init(impl FileDescriptionImpl, statusFlags uint32, mnt *Mount, d *Dentry, opts *FileDescriptionOptions)

Init must be called before first use of fd. It takes ownership of references on mnt and d held by the caller. statusFlags is the initial file description status flags, which is usually the full set of flags passed to open(2).

func (*FileDescription) InodeID

func (fd *FileDescription) InodeID() uint64

InodeID implements memmap.MappingIdentity.InodeID.

func (*FileDescription) Ioctl

Ioctl implements the ioctl(2) syscall.

func (*FileDescription) IterDirents

func (fd *FileDescription) IterDirents(ctx context.Context, cb IterDirentsCallback) error

IterDirents invokes cb on each entry in the directory represented by fd. If IterDirents has been called since the last call to Seek, it continues iteration from the end of the last call.

func (*FileDescription) Listxattr

func (fd *FileDescription) Listxattr(ctx context.Context) ([]string, error)

Listxattr returns all extended attribute names for the file represented by fd.

func (*FileDescription) MappedName

func (fd *FileDescription) MappedName(ctx context.Context) string

MappedName implements memmap.MappingIdentity.MappedName.

func (*FileDescription) Mount

func (fd *FileDescription) Mount() *Mount

Mount returns the mount on which fd was opened. It does not take a reference on the returned Mount.

func (*FileDescription) Msync

Msync implements memmap.MappingIdentity.Msync.

func (*FileDescription) OnClose

func (fd *FileDescription) OnClose(ctx context.Context) error

OnClose is called when a file descriptor representing the FileDescription is closed. Returning a non-nil error should not prevent the file descriptor from being closed.

func (*FileDescription) PRead

func (fd *FileDescription) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts ReadOptions) (int64, error)

PRead reads from the file represented by fd into dst, starting at the given offset, and returns the number of bytes read. PRead is permitted to return partial reads with a nil error.

func (*FileDescription) PWrite

func (fd *FileDescription) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts WriteOptions) (int64, error)

PWrite writes src to the file represented by fd, starting at the given offset, and returns the number of bytes written. PWrite is permitted to return partial writes with a nil error.

func (*FileDescription) Read

Read is similar to PRead, but does not specify an offset.

func (*FileDescription) Removexattr

func (fd *FileDescription) Removexattr(ctx context.Context, name string) error

Removexattr removes the given extended attribute from the file represented by fd.

func (*FileDescription) Seek

func (fd *FileDescription) Seek(ctx context.Context, offset int64, whence int32) (int64, error)

Seek changes fd's offset (assuming one exists) and returns its new value.

func (*FileDescription) SetStat

func (fd *FileDescription) SetStat(ctx context.Context, opts SetStatOptions) error

SetStat updates metadata for the file represented by fd.

func (*FileDescription) SetStatusFlags

func (fd *FileDescription) SetStatusFlags(ctx context.Context, creds *auth.Credentials, flags uint32) error

SetStatusFlags sets file description status flags, as for fcntl(F_SETFL).

func (*FileDescription) Setxattr

func (fd *FileDescription) Setxattr(ctx context.Context, opts SetxattrOptions) error

Setxattr changes the value associated with the given extended attribute for the file represented by fd.

func (*FileDescription) Stat

func (fd *FileDescription) Stat(ctx context.Context, opts StatOptions) (linux.Statx, error)

Stat returns metadata for the file represented by fd.

func (*FileDescription) StatFS

func (fd *FileDescription) StatFS(ctx context.Context) (linux.Statfs, error)

StatFS returns metadata for the filesystem containing the file represented by fd.

func (*FileDescription) StatusFlags

func (fd *FileDescription) StatusFlags() uint32

StatusFlags returns file description status flags, as for fcntl(F_GETFL).

func (*FileDescription) Sync

func (fd *FileDescription) Sync(ctx context.Context) error

Sync has the semantics of fsync(2).

func (*FileDescription) SyncFS

func (fd *FileDescription) SyncFS(ctx context.Context) error

SyncFS instructs the filesystem containing fd to execute the semantics of syncfs(2).

func (*FileDescription) TryIncRef

func (fd *FileDescription) TryIncRef() bool

TryIncRef increments fd's reference count and returns true. If fd's reference count is already zero, TryIncRef does nothing and returns false.

TryIncRef does not require that a reference is held on fd.

func (*FileDescription) VirtualDentry

func (fd *FileDescription) VirtualDentry() VirtualDentry

VirtualDentry returns the location at which fd was opened. It does not take a reference on the returned VirtualDentry.

func (*FileDescription) Write

Write is similar to PWrite, but does not specify an offset.

type FileDescriptionDefaultImpl

type FileDescriptionDefaultImpl struct{}

FileDescriptionDefaultImpl may be embedded by implementations of FileDescriptionImpl to obtain implementations of many FileDescriptionImpl methods with default behavior analogous to Linux's.

func (FileDescriptionDefaultImpl) ConfigureMMap

func (FileDescriptionDefaultImpl) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error

ConfigureMMap implements FileDescriptionImpl.ConfigureMMap analogously to file_operations::mmap == NULL in Linux.

func (FileDescriptionDefaultImpl) EventRegister

func (FileDescriptionDefaultImpl) EventRegister(e *waiter.Entry, mask waiter.EventMask)

EventRegister implements waiter.Waitable.EventRegister analogously to file_operations::poll == NULL in Linux.

func (FileDescriptionDefaultImpl) EventUnregister

func (FileDescriptionDefaultImpl) EventUnregister(e *waiter.Entry)

EventUnregister implements waiter.Waitable.EventUnregister analogously to file_operations::poll == NULL in Linux.

func (FileDescriptionDefaultImpl) Getxattr

Getxattr implements FileDescriptionImpl.Getxattr analogously to inode::i_opflags & IOP_XATTR == 0 in Linux.

func (FileDescriptionDefaultImpl) Ioctl

Ioctl implements FileDescriptionImpl.Ioctl analogously to file_operations::unlocked_ioctl == NULL in Linux.

func (FileDescriptionDefaultImpl) IterDirents

IterDirents implements FileDescriptionImpl.IterDirents analogously to file_operations::iterate == file_operations::iterate_shared == NULL in Linux.

func (FileDescriptionDefaultImpl) Listxattr

Listxattr implements FileDescriptionImpl.Listxattr analogously to inode_operations::listxattr == NULL in Linux.

func (FileDescriptionDefaultImpl) OnClose

OnClose implements FileDescriptionImpl.OnClose analogously to file_operations::flush == NULL in Linux.

func (FileDescriptionDefaultImpl) PRead

PRead implements FileDescriptionImpl.PRead analogously to file_operations::read == file_operations::read_iter == NULL in Linux.

func (FileDescriptionDefaultImpl) PWrite

PWrite implements FileDescriptionImpl.PWrite analogously to file_operations::write == file_operations::write_iter == NULL in Linux.

func (FileDescriptionDefaultImpl) Read

Read implements FileDescriptionImpl.Read analogously to file_operations::read == file_operations::read_iter == NULL in Linux.

func (FileDescriptionDefaultImpl) Readiness

Readiness implements waiter.Waitable.Readiness analogously to file_operations::poll == NULL in Linux.

func (FileDescriptionDefaultImpl) Removexattr

func (FileDescriptionDefaultImpl) Removexattr(ctx context.Context, name string) error

Removexattr implements FileDescriptionImpl.Removexattr analogously to inode::i_opflags & IOP_XATTR == 0 in Linux.

func (FileDescriptionDefaultImpl) Seek

func (FileDescriptionDefaultImpl) Seek(ctx context.Context, offset int64, whence int32) (int64, error)

Seek implements FileDescriptionImpl.Seek analogously to file_operations::llseek == NULL in Linux.

func (FileDescriptionDefaultImpl) Setxattr

Setxattr implements FileDescriptionImpl.Setxattr analogously to inode::i_opflags & IOP_XATTR == 0 in Linux.

func (FileDescriptionDefaultImpl) StatFS

StatFS implements FileDescriptionImpl.StatFS analogously to super_operations::statfs == NULL in Linux.

func (FileDescriptionDefaultImpl) Sync

Sync implements FileDescriptionImpl.Sync analogously to file_operations::fsync == NULL in Linux.

func (FileDescriptionDefaultImpl) Write

Write implements FileDescriptionImpl.Write analogously to file_operations::write == file_operations::write_iter == NULL in Linux.

type FileDescriptionImpl

type FileDescriptionImpl interface {
	// Release is called when the associated FileDescription reaches zero
	// references.
	Release()

	// OnClose is called when a file descriptor representing the
	// FileDescription is closed. Note that returning a non-nil error does not
	// prevent the file descriptor from being closed.
	OnClose(ctx context.Context) error

	// Stat returns metadata for the file represented by the FileDescription.
	Stat(ctx context.Context, opts StatOptions) (linux.Statx, error)

	// SetStat updates metadata for the file represented by the
	// FileDescription.
	SetStat(ctx context.Context, opts SetStatOptions) error

	// StatFS returns metadata for the filesystem containing the file
	// represented by the FileDescription.
	StatFS(ctx context.Context) (linux.Statfs, error)

	// waiter.Waitable methods may be used to poll for I/O events.
	waiter.Waitable

	// PRead reads from the file into dst, starting at the given offset, and
	// returns the number of bytes read. PRead is permitted to return partial
	// reads with a nil error.
	PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts ReadOptions) (int64, error)

	// Read is similar to PRead, but does not specify an offset.
	//
	// For files with an implicit FileDescription offset (e.g. regular files),
	// Read begins at the FileDescription offset, and advances the offset by
	// the number of bytes read; note that POSIX 2.9.7 "Thread Interactions
	// with Regular File Operations" requires that all operations that may
	// mutate the FileDescription offset are serialized.
	Read(ctx context.Context, dst usermem.IOSequence, opts ReadOptions) (int64, error)

	// PWrite writes src to the file, starting at the given offset, and returns
	// the number of bytes written. PWrite is permitted to return partial
	// writes with a nil error.
	//
	// As in Linux (but not POSIX), if O_APPEND is in effect for the
	// FileDescription, PWrite should ignore the offset and append data to the
	// end of the file.
	PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts WriteOptions) (int64, error)

	// Write is similar to PWrite, but does not specify an offset, which is
	// implied as for Read.
	//
	// Write is a FileDescriptionImpl method, instead of a wrapper around
	// PWrite that uses a FileDescription offset, to make it possible for
	// remote filesystems to implement O_APPEND correctly (i.e. atomically with
	// respect to writers outside the scope of VFS).
	Write(ctx context.Context, src usermem.IOSequence, opts WriteOptions) (int64, error)

	// IterDirents invokes cb on each entry in the directory represented by the
	// FileDescription. If IterDirents has been called since the last call to
	// Seek, it continues iteration from the end of the last call.
	IterDirents(ctx context.Context, cb IterDirentsCallback) error

	// Seek changes the FileDescription offset (assuming one exists) and
	// returns its new value.
	//
	// For directories, if whence == SEEK_SET and offset == 0, the caller is
	// rewinddir(), such that Seek "shall also cause the directory stream to
	// refer to the current state of the corresponding directory" -
	// POSIX.1-2017.
	Seek(ctx context.Context, offset int64, whence int32) (int64, error)

	// Sync requests that cached state associated with the file represented by
	// the FileDescription is synchronized with persistent storage, and blocks
	// until this is complete.
	Sync(ctx context.Context) error

	// ConfigureMMap mutates opts to implement mmap(2) for the file. Most
	// implementations that support memory mapping can call
	// GenericConfigureMMap with the appropriate memmap.Mappable.
	ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error

	// Ioctl implements the ioctl(2) syscall.
	Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallArguments) (uintptr, error)

	// Listxattr returns all extended attribute names for the file.
	Listxattr(ctx context.Context) ([]string, error)

	// Getxattr returns the value associated with the given extended attribute
	// for the file.
	Getxattr(ctx context.Context, name string) (string, error)

	// Setxattr changes the value associated with the given extended attribute
	// for the file.
	Setxattr(ctx context.Context, opts SetxattrOptions) error

	// Removexattr removes the given extended attribute from the file.
	Removexattr(ctx context.Context, name string) error
}

FileDescriptionImpl contains implementation details for an FileDescription. Implementations of FileDescriptionImpl should contain their associated FileDescription by value as their first field.

For all functions that return linux.Statx, Statx.Uid and Statx.Gid will be interpreted as IDs in the root UserNamespace (i.e. as auth.KUID and auth.KGID respectively).

FileDescriptionImpl is analogous to Linux's struct file_operations.

type FileDescriptionOptions

type FileDescriptionOptions struct {
	// If AllowDirectIO is true, allow O_DIRECT to be set on the file. This is
	// usually only the case if O_DIRECT would actually have an effect.
	AllowDirectIO bool
}

FileDescriptionOptions contains options to FileDescription.Init().

type Filesystem

type Filesystem struct {
	// contains filtered or unexported fields
}

A Filesystem is a tree of nodes represented by Dentries, which forms part of a VirtualFilesystem.

Filesystems are reference-counted. Unless otherwise specified, all Filesystem methods require that a reference is held.

Filesystem is analogous to Linux's struct super_block.

func (*Filesystem) DecRef

func (fs *Filesystem) DecRef()

DecRef decrements fs' reference count.

func (*Filesystem) Impl

func (fs *Filesystem) Impl() FilesystemImpl

Impl returns the FilesystemImpl associated with fs.

func (*Filesystem) IncRef

func (fs *Filesystem) IncRef()

IncRef increments fs' reference count.

func (*Filesystem) Init

func (fs *Filesystem) Init(vfsObj *VirtualFilesystem, impl FilesystemImpl)

Init must be called before first use of fs.

func (*Filesystem) TryIncRef

func (fs *Filesystem) TryIncRef() bool

TryIncRef increments fs' reference count and returns true. If fs' reference count is zero, TryIncRef does nothing and returns false.

TryIncRef does not require that a reference is held on fs.

func (*Filesystem) VirtualFilesystem

func (fs *Filesystem) VirtualFilesystem() *VirtualFilesystem

VirtualFilesystem returns the containing VirtualFilesystem.

type FilesystemImpl

type FilesystemImpl interface {
	// Release is called when the associated Filesystem reaches zero
	// references.
	Release()

	// Sync "causes all pending modifications to filesystem metadata and cached
	// file data to be written to the underlying [filesystem]", as by syncfs(2).
	Sync(ctx context.Context) error

	// GetDentryAt returns a Dentry representing the file at rp. A reference is
	// taken on the returned Dentry.
	//
	// GetDentryAt does not correspond directly to a Linux syscall; it is used
	// in the implementation of:
	//
	// - Syscalls that need to resolve two paths: rename(), renameat(),
	// renameat2(), link(), linkat().
	//
	// - Syscalls that need to refer to a filesystem position outside the
	// context of a file description: chdir(), fchdir(), chroot(), mount(),
	// umount().
	GetDentryAt(ctx context.Context, rp *ResolvingPath, opts GetDentryOptions) (*Dentry, error)

	// LinkAt creates a hard link at rp representing the same file as vd. It
	// does not take ownership of references on vd.
	//
	// The implementation is responsible for checking that vd.Mount() ==
	// rp.Mount(), and that vd does not represent a directory.
	LinkAt(ctx context.Context, rp *ResolvingPath, vd VirtualDentry) error

	// MkdirAt creates a directory at rp.
	MkdirAt(ctx context.Context, rp *ResolvingPath, opts MkdirOptions) error

	// MknodAt creates a regular file, device special file, or named pipe at
	// rp.
	MknodAt(ctx context.Context, rp *ResolvingPath, opts MknodOptions) error

	// OpenAt returns an FileDescription providing access to the file at rp. A
	// reference is taken on the returned FileDescription.
	OpenAt(ctx context.Context, rp *ResolvingPath, opts OpenOptions) (*FileDescription, error)

	// ReadlinkAt returns the target of the symbolic link at rp.
	ReadlinkAt(ctx context.Context, rp *ResolvingPath) (string, error)

	// RenameAt renames the Dentry represented by vd to rp. It does not take
	// ownership of references on vd.
	//
	// The implementation is responsible for checking that vd.Mount() ==
	// rp.Mount().
	RenameAt(ctx context.Context, rp *ResolvingPath, vd VirtualDentry, opts RenameOptions) error

	// RmdirAt removes the directory at rp.
	RmdirAt(ctx context.Context, rp *ResolvingPath) error

	// SetStatAt updates metadata for the file at the given path.
	SetStatAt(ctx context.Context, rp *ResolvingPath, opts SetStatOptions) error

	// StatAt returns metadata for the file at rp.
	StatAt(ctx context.Context, rp *ResolvingPath, opts StatOptions) (linux.Statx, error)

	// StatFSAt returns metadata for the filesystem containing the file at rp.
	// (This method takes a path because a FilesystemImpl may consist of any
	// number of constituent filesystems.)
	StatFSAt(ctx context.Context, rp *ResolvingPath) (linux.Statfs, error)

	// SymlinkAt creates a symbolic link at rp referring to the given target.
	SymlinkAt(ctx context.Context, rp *ResolvingPath, target string) error

	// UnlinkAt removes the non-directory file at rp.
	UnlinkAt(ctx context.Context, rp *ResolvingPath) error

	// ListxattrAt returns all extended attribute names for the file at rp.
	ListxattrAt(ctx context.Context, rp *ResolvingPath) ([]string, error)

	// GetxattrAt returns the value associated with the given extended
	// attribute for the file at rp.
	GetxattrAt(ctx context.Context, rp *ResolvingPath, name string) (string, error)

	// SetxattrAt changes the value associated with the given extended
	// attribute for the file at rp.
	SetxattrAt(ctx context.Context, rp *ResolvingPath, opts SetxattrOptions) error

	// RemovexattrAt removes the given extended attribute from the file at rp.
	RemovexattrAt(ctx context.Context, rp *ResolvingPath, name string) error

	// PrependPath prepends a path from vd to vd.Mount().Root() to b.
	//
	// If vfsroot.Ok(), it is the contextual VFS root; if it is encountered
	// before vd.Mount().Root(), PrependPath should stop prepending path
	// components and return a PrependPathAtVFSRootError.
	//
	// If traversal of vd.Dentry()'s ancestors encounters an independent
	// ("root") Dentry that is not vd.Mount().Root() (i.e. vd.Dentry() is not a
	// descendant of vd.Mount().Root()), PrependPath should stop prepending
	// path components and return a PrependPathAtNonMountRootError.
	//
	// Filesystems for which Dentries do not have meaningful paths may prepend
	// an arbitrary descriptive string to b and then return a
	// PrependPathSyntheticError.
	//
	// Most implementations can acquire the appropriate locks to ensure that
	// Dentry.Name() and Dentry.Parent() are fixed for vd.Dentry() and all of
	// its ancestors, then call GenericPrependPath.
	//
	// Preconditions: vd.Mount().Filesystem().Impl() == this FilesystemImpl.
	PrependPath(ctx context.Context, vfsroot, vd VirtualDentry, b *fspath.Builder) error
}

FilesystemImpl contains implementation details for a Filesystem. Implementations of FilesystemImpl should contain their associated Filesystem by value as their first field.

All methods that take a ResolvingPath must resolve the path before performing any other checks, including rejection of the operation if not supported by the FilesystemImpl. This is because the final FilesystemImpl (responsible for actually implementing the operation) isn't known until path resolution is complete.

For all methods that take or return linux.Statx, Statx.Uid and Statx.Gid should be interpreted as IDs in the root UserNamespace (i.e. as auth.KUID and auth.KGID respectively).

FilesystemImpl combines elements of Linux's struct super_operations and struct inode_operations, for reasons described in the documentation for Dentry.

type FilesystemType

type FilesystemType interface {
	// GetFilesystem returns a Filesystem configured by the given options,
	// along with its mount root. A reference is taken on the returned
	// Filesystem and Dentry.
	GetFilesystem(ctx context.Context, vfsObj *VirtualFilesystem, creds *auth.Credentials, source string, opts GetFilesystemOptions) (*Filesystem, *Dentry, error)
}

A FilesystemType constructs filesystems.

FilesystemType is analogous to Linux's struct file_system_type.

type GetDentryOptions

type GetDentryOptions struct {
	// If CheckSearchable is true, FilesystemImpl.GetDentryAt() must check that
	// the returned Dentry is a directory for which creds has search
	// permission.
	CheckSearchable bool
}

GetDentryOptions contains options to VirtualFilesystem.GetDentryAt() and FilesystemImpl.GetDentryAt().

type GetFilesystemOptions

type GetFilesystemOptions struct {
	// Data is the string passed as the 5th argument to mount(2), which is
	// usually a comma-separated list of filesystem-specific mount options.
	Data string

	// InternalData holds opaque FilesystemType-specific data. There is
	// intentionally no way for applications to specify InternalData; if it is
	// not nil, the call to GetFilesystem originates from within the sentry.
	InternalData interface{}
}

GetFilesystemOptions contains options to FilesystemType.GetFilesystem.

type IterDirentsCallback

type IterDirentsCallback interface {
	// Handle handles the given iterated Dirent. It returns true if iteration
	// should continue, and false if FileDescriptionImpl.IterDirents should
	// terminate now and restart with the same Dirent the next time it is
	// called.
	Handle(dirent Dirent) bool
}

IterDirentsCallback receives Dirents from FileDescriptionImpl.IterDirents.

type MkdirOptions

type MkdirOptions struct {
	// Mode is the file mode bits for the created directory.
	Mode linux.FileMode
}

MkdirOptions contains options to VirtualFilesystem.MkdirAt() and FilesystemImpl.MkdirAt().

type MknodOptions

type MknodOptions struct {
	// Mode is the file type and mode bits for the created file.
	Mode linux.FileMode

	// If Mode specifies a character or block device special file, DevMajor and
	// DevMinor are the major and minor device numbers for the created device.
	DevMajor uint32
	DevMinor uint32
}

MknodOptions contains options to VirtualFilesystem.MknodAt() and FilesystemImpl.MknodAt().

type Mount

type Mount struct {
	// contains filtered or unexported fields
}

A Mount is a replacement of a Dentry (Mount.key.point) from one Filesystem (Mount.key.parent.fs) with a Dentry (Mount.root) from another Filesystem (Mount.fs), which applies to path resolution in the context of a particular Mount (Mount.key.parent).

Mounts are reference-counted. Unless otherwise specified, all Mount methods require that a reference is held.

Mount and Filesystem are distinct types because it's possible for a single Filesystem to be mounted at multiple locations and/or in multiple mount namespaces.

Mount is analogous to Linux's struct mount. (gVisor does not distinguish between struct mount and struct vfsmount.)

func (*Mount) CheckBeginWrite

func (mnt *Mount) CheckBeginWrite() error

CheckBeginWrite increments the counter of in-progress write operations on mnt. If mnt is mounted MS_RDONLY, CheckBeginWrite does nothing and returns EROFS.

If CheckBeginWrite succeeds, EndWrite must be called when the write operation is finished.

func (*Mount) DecRef

func (mnt *Mount) DecRef()

DecRef decrements mnt's reference count.

func (*Mount) EndWrite

func (mnt *Mount) EndWrite()

EndWrite indicates that a write operation signaled by a previous successful call to CheckBeginWrite has finished.

func (*Mount) Filesystem

func (mnt *Mount) Filesystem() *Filesystem

Filesystem returns the mounted Filesystem. It does not take a reference on the returned Filesystem.

func (*Mount) IncRef

func (mnt *Mount) IncRef()

IncRef increments mnt's reference count.

type MountNamespace

type MountNamespace struct {
	// contains filtered or unexported fields
}

A MountNamespace is a collection of Mounts.

MountNamespaces are reference-counted. Unless otherwise specified, all MountNamespace methods require that a reference is held.

MountNamespace is analogous to Linux's struct mnt_namespace.

func MountNamespaceFromContext

func MountNamespaceFromContext(ctx context.Context) *MountNamespace

MountNamespaceFromContext returns the MountNamespace used by ctx. It does not take a reference on the returned MountNamespace. If ctx is not associated with a MountNamespace, MountNamespaceFromContext returns nil.

func (*MountNamespace) DecRef

func (mntns *MountNamespace) DecRef(vfs *VirtualFilesystem)

DecRef decrements mntns' reference count.

func (*MountNamespace) IncRef

func (mntns *MountNamespace) IncRef()

IncRef increments mntns' reference count.

func (*MountNamespace) Root

func (mntns *MountNamespace) Root() VirtualDentry

Root returns mntns' root. A reference is taken on the returned VirtualDentry.

type MountOptions

type MountOptions struct {
	// GetFilesystemOptions contains options to FilesystemType.GetFilesystem().
	GetFilesystemOptions GetFilesystemOptions
}

MountOptions contains options to VirtualFilesystem.MountAt().

type OpenOptions

type OpenOptions struct {
	// Flags contains access mode and flags as specified for open(2).
	//
	// FilesystemImpls is reponsible for implementing the following flags:
	// O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_CREAT, O_DIRECT, O_DSYNC,
	// O_EXCL, O_NOATIME, O_NOCTTY, O_NONBLOCK, O_PATH, O_SYNC, O_TMPFILE, and
	// O_TRUNC. VFS is responsible for handling O_DIRECTORY, O_LARGEFILE, and
	// O_NOFOLLOW. VFS users are responsible for handling O_CLOEXEC, since file
	// descriptors are mostly outside the scope of VFS.
	Flags uint32

	// If FilesystemImpl.OpenAt() creates a file, Mode is the file mode for the
	// created file.
	Mode linux.FileMode
}

OpenOptions contains options to VirtualFilesystem.OpenAt() and FilesystemImpl.OpenAt().

type PathOperation

type PathOperation struct {
	// Root is the VFS root. References on Root are borrowed from the provider
	// of the PathOperation.
	//
	// Invariants: Root.Ok().
	Root VirtualDentry

	// Start is the starting point for the path traversal. References on Start
	// are borrowed from the provider of the PathOperation (i.e. the caller of
	// the VFS method to which the PathOperation was passed).
	//
	// Invariants: Start.Ok(). If Pathname.Absolute, then Start == Root.
	Start VirtualDentry

	// Path is the pathname traversed by this operation.
	Pathname string

	// If FollowFinalSymlink is true, and the Dentry traversed by the final
	// path component represents a symbolic link, the symbolic link should be
	// followed.
	FollowFinalSymlink bool
}

PathOperation specifies the path operated on by a VFS method.

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.)

type PrependPathAtNonMountRootError

type PrependPathAtNonMountRootError struct{}

PrependPathAtNonMountRootError is returned by implementations of FilesystemImpl.PrependPath() when they encounter an independent ancestor Dentry that is not the Mount root.

func (PrependPathAtNonMountRootError) Error

Error implements error.Error.

type PrependPathAtVFSRootError

type PrependPathAtVFSRootError struct{}

PrependPathAtVFSRootError is returned by implementations of FilesystemImpl.PrependPath() when they encounter the contextual VFS root.

func (PrependPathAtVFSRootError) Error

Error implements error.Error.

type PrependPathSyntheticError

type PrependPathSyntheticError struct{}

PrependPathSyntheticError is returned by implementations of FilesystemImpl.PrependPath() for which prepended names do not represent real paths.

func (PrependPathSyntheticError) Error

Error implements error.Error.

type ReadOptions

type ReadOptions struct {
	// Flags contains flags as specified for preadv2(2).
	Flags uint32
}

ReadOptions contains options to FileDescription.PRead(), FileDescriptionImpl.PRead(), FileDescription.Read(), and FileDescriptionImpl.Read().

type RenameOptions

type RenameOptions struct {
	// Flags contains flags as specified for renameat2(2).
	Flags uint32
}

RenameOptions contains options to VirtualFilesystem.RenameAt() and FilesystemImpl.RenameAt().

type ResolvingPath

type ResolvingPath struct {
	// contains filtered or unexported fields
}

ResolvingPath represents the state of an in-progress path resolution, shared between VFS and FilesystemImpl methods that take a path.

From the perspective of FilesystemImpl methods, a ResolvingPath represents a starting Dentry on the associated Filesystem (on which a reference is already held) and a stream of path components relative to that Dentry.

ResolvingPath is loosely analogous to Linux's struct nameidata.

func (*ResolvingPath) Advance

func (rp *ResolvingPath) Advance()

Advance advances the stream of path components represented by rp.

Preconditions: !rp.Done().

func (*ResolvingPath) Component

func (rp *ResolvingPath) Component() string

Component returns the current path component in the stream represented by rp.

Preconditions: !rp.Done().

func (*ResolvingPath) Credentials

func (rp *ResolvingPath) Credentials() *auth.Credentials

Credentials returns the credentials of rp's provider.

func (*ResolvingPath) Done

func (rp *ResolvingPath) Done() bool

Done returns true if there are no remaining path components in the stream represented by rp.

func (*ResolvingPath) Final

func (rp *ResolvingPath) Final() bool

Final returns true if there is exactly one remaining path component in the stream represented by rp.

Preconditions: !rp.Done().

func (*ResolvingPath) HandleJump

func (rp *ResolvingPath) HandleJump(target VirtualDentry) error

HandleJump is called when the current path component is a "magic" link to the given VirtualDentry, like /proc/[pid]/fd/[fd]. If the calling Filesystem method should continue path traversal, HandleMagicSymlink updates the path component stream to reflect the magic link target and returns nil. Otherwise it returns a non-nil error.

Preconditions: !rp.Done().

func (rp *ResolvingPath) HandleSymlink(target string) error

HandleSymlink is called when the current path component is a symbolic link to the given target. If the calling Filesystem method should continue path traversal, HandleSymlink updates the path component stream to reflect the symlink target and returns nil. Otherwise it returns a non-nil error.

Preconditions: !rp.Done().

func (*ResolvingPath) Mount

func (rp *ResolvingPath) Mount() *Mount

Mount returns the Mount on which path resolution is currently occurring. It does not take a reference on the returned Mount.

func (*ResolvingPath) MustBeDir

func (rp *ResolvingPath) MustBeDir() bool

MustBeDir returns true if the file traversed by rp must be a directory.

func (*ResolvingPath) ResolveChild

func (rp *ResolvingPath) ResolveChild(d *Dentry, name string) (*Dentry, error)

ResolveChild returns the VFS child of d with the given name. It does not take a reference on the returned Dentry. If no such child exists, ResolveChild returns (nil, nil).

Preconditions: There are no concurrent mutators of d.

func (*ResolvingPath) ResolveComponent

func (rp *ResolvingPath) ResolveComponent(d *Dentry) (*Dentry, error)

ResolveComponent returns the Dentry reached by starting at d and resolving the current path component in the stream represented by rp. It does not advance the stream. It does not take a reference on the returned Dentry. If no such Dentry exists, ResolveComponent returns (nil, nil).

Preconditions: !rp.Done(). There are no concurrent mutators of d.

func (*ResolvingPath) ResolveParent

func (rp *ResolvingPath) ResolveParent(d *Dentry) (*Dentry, error)

ResolveParent returns the VFS parent of d. It does not take a reference on the returned Dentry.

Preconditions: There are no concurrent mutators of d.

Postconditions: If the returned error is nil, then the returned Dentry is not nil.

func (*ResolvingPath) Restart

func (rp *ResolvingPath) Restart()

Restart resets the stream of path components represented by rp to its state on entry to the current FilesystemImpl method.

func (rp *ResolvingPath) ShouldFollowSymlink() bool

ShouldFollowSymlink returns true if, supposing that the current path component in pcs represents a symbolic link, the symbolic link should be followed.

Preconditions: !rp.Done().

func (*ResolvingPath) Start

func (rp *ResolvingPath) Start() *Dentry

Start returns the starting Dentry represented by rp. It does not take a reference on the returned Dentry.

func (*ResolvingPath) VirtualFilesystem

func (rp *ResolvingPath) VirtualFilesystem() *VirtualFilesystem

VirtualFilesystem returns the containing VirtualFilesystem.

type SetStatOptions

type SetStatOptions struct {
	// Stat is the metadata that should be set. Only fields indicated by
	// Stat.Mask should be set.
	//
	// If Stat specifies that a timestamp should be set,
	// FilesystemImpl.SetStatAt() and FileDescriptionImpl.SetStat() must
	// special-case StatxTimestamp.Nsec == UTIME_NOW as described by
	// utimensat(2); however, they do not need to check for StatxTimestamp.Nsec
	// == UTIME_OMIT (VFS users must unset the corresponding bit in Stat.Mask
	// instead).
	Stat linux.Statx
}

SetStatOptions contains options to VirtualFilesystem.SetStatAt(), FilesystemImpl.SetStatAt(), FileDescription.SetStat(), and FileDescriptionImpl.SetStat().

type SetxattrOptions

type SetxattrOptions struct {
	// Name is the name of the extended attribute being mutated.
	Name string

	// Value is the extended attribute's new value.
	Value string

	// Flags contains flags as specified for setxattr/lsetxattr/fsetxattr(2).
	Flags uint32
}

SetxattrOptions contains options to VirtualFilesystem.SetxattrAt(), FilesystemImpl.SetxattrAt(), FileDescription.Setxattr(), and FileDescriptionImpl.Setxattr().

type StatOptions

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.
	//
	// The FilesystemImpl or FileDescriptionImpl may return fields not
	// requested in Mask, and may fail to return fields requested in Mask that
	// are not supported by the underlying filesystem implementation, without
	// returning an error.
	Mask uint32

	// Sync specifies the synchronization required, and is one of
	// linux.AT_STATX_SYNC_AS_STAT (which is 0, and therefore the default),
	// linux.AT_STATX_SYNC_FORCE_SYNC, or linux.AT_STATX_SYNC_DONT_SYNC.
	Sync uint32
}

StatOptions contains options to VirtualFilesystem.StatAt(), FilesystemImpl.StatAt(), FileDescription.Stat(), and FileDescriptionImpl.Stat().

type UmountOptions

type UmountOptions struct {
	// Flags contains flags as specified for umount2(2).
	Flags uint32
}

UmountOptions contains options to VirtualFilesystem.UmountAt().

type VirtualDentry

type VirtualDentry struct {
	// contains filtered or unexported fields
}

A VirtualDentry represents a node in a VFS tree, by combining a Dentry (which represents a node in a Filesystem's tree) and a Mount (which represents the Filesystem's position in a VFS mount tree).

VirtualDentry's semantics are similar to that of a Go interface object representing a pointer: it is a copyable value type that represents references to another entity. The zero value of VirtualDentry is an "empty VirtualDentry", directly analogous to a nil interface object. VirtualDentry.Ok() checks that a VirtualDentry is not zero-valued; unless otherwise specified, all other VirtualDentry methods require VirtualDentry.Ok() == true.

Mounts and Dentries are reference-counted, requiring that users call VirtualDentry.{Inc,Dec}Ref() as appropriate. We often colloquially refer to references on the Mount and Dentry referred to by a VirtualDentry as references on the VirtualDentry itself. Unless otherwise specified, all VirtualDentry methods require that a reference is held on the VirtualDentry.

VirtualDentry is analogous to Linux's struct path.

func RootFromContext

func RootFromContext(ctx context.Context) VirtualDentry

RootFromContext returns the VFS root used by ctx. It takes a reference on the returned VirtualDentry. If ctx does not have a specific VFS root, RootFromContext returns a zero-value VirtualDentry.

func (VirtualDentry) DecRef

func (vd VirtualDentry) DecRef()

DecRef decrements the reference counts on the Mount and Dentry represented by vd.

func (VirtualDentry) Dentry

func (vd VirtualDentry) Dentry() *Dentry

Dentry returns the Dentry associated with vd. It does not take a reference on the returned Dentry.

func (VirtualDentry) IncRef

func (vd VirtualDentry) IncRef()

IncRef increments the reference counts on the Mount and Dentry represented by vd.

func (VirtualDentry) Mount

func (vd VirtualDentry) Mount() *Mount

Mount returns the Mount associated with vd. It does not take a reference on the returned Mount.

func (VirtualDentry) Ok

func (vd VirtualDentry) Ok() bool

Ok returns true if vd is not empty. It does not require that a reference is held.

type VirtualFilesystem

type VirtualFilesystem struct {
	// contains filtered or unexported fields
}

A VirtualFilesystem (VFS for short) combines Filesystems in trees of Mounts.

There is no analogue to the VirtualFilesystem type in Linux, as the equivalent state in Linux is global.

func New

func New() *VirtualFilesystem

New returns a new VirtualFilesystem with no mounts or FilesystemTypes.

func (*VirtualFilesystem) AbortDeleteDentry

func (vfs *VirtualFilesystem) AbortDeleteDentry(d *Dentry)

AbortDeleteDentry must be called after PrepareDeleteDentry if the deletion fails.

func (*VirtualFilesystem) AbortRenameDentry

func (vfs *VirtualFilesystem) AbortRenameDentry(from, to *Dentry)

AbortRenameDentry must be called after PrepareRenameDentry if the rename fails.

func (*VirtualFilesystem) CommitDeleteDentry

func (vfs *VirtualFilesystem) CommitDeleteDentry(d *Dentry)

CommitDeleteDentry must be called after the file represented by d is deleted, and causes d to become disowned.

CommitDeleteDentry is a mutator of d and d.Parent().

Preconditions: PrepareDeleteDentry was previously called on d.

func (*VirtualFilesystem) CommitRenameExchangeDentry

func (vfs *VirtualFilesystem) CommitRenameExchangeDentry(from, to *Dentry)

CommitRenameExchangeDentry must be called after the files represented by from and to are exchanged by rename(RENAME_EXCHANGE).

CommitRenameExchangeDentry is a mutator of from, to, from.Parent(), and to.Parent().

Preconditions: PrepareRenameDentry was previously called on from and to.

func (*VirtualFilesystem) CommitRenameReplaceDentry

func (vfs *VirtualFilesystem) CommitRenameReplaceDentry(from, newParent *Dentry, newName string, to *Dentry)

CommitRenameReplaceDentry must be called after the file represented by from is renamed without RENAME_EXCHANGE. If to is not nil, it represents the file that was replaced by from.

CommitRenameReplaceDentry is a mutator of from, to, from.Parent(), and to.Parent().

Preconditions: PrepareRenameDentry was previously called on from and to. newParent.Child(newName) == to.

func (*VirtualFilesystem) DeleteDentry

func (vfs *VirtualFilesystem) DeleteDentry(mntns *MountNamespace, d *Dentry) error

DeleteDentry combines PrepareDeleteDentry and CommitDeleteDentry, as appropriate for in-memory filesystems that don't need to ensure that some external state change succeeds before committing the deletion.

DeleteDentry is a mutator of d and d.Parent().

Preconditions: d is a child Dentry.

func (*VirtualFilesystem) ForceDeleteDentry

func (vfs *VirtualFilesystem) ForceDeleteDentry(d *Dentry)

ForceDeleteDentry causes d to become disowned. It should only be used in cases where VFS has no ability to stop the deletion (e.g. d represents the local state of a file on a remote filesystem on which the file has already been deleted).

ForceDeleteDentry is a mutator of d and d.Parent().

Preconditions: d is a child Dentry.

func (*VirtualFilesystem) GetDentryAt

func (vfs *VirtualFilesystem) GetDentryAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *GetDentryOptions) (VirtualDentry, error)

GetDentryAt returns a VirtualDentry representing the given path, at which a file must exist. A reference is taken on the returned VirtualDentry.

func (*VirtualFilesystem) GetxattrAt

func (vfs *VirtualFilesystem) GetxattrAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, name string) (string, error)

GetxattrAt returns the value associated with the given extended attribute for the file at the given path.

func (*VirtualFilesystem) LinkAt

func (vfs *VirtualFilesystem) LinkAt(ctx context.Context, creds *auth.Credentials, oldpop, newpop *PathOperation) error

LinkAt creates a hard link at newpop representing the existing file at oldpop.

func (*VirtualFilesystem) ListxattrAt

func (vfs *VirtualFilesystem) ListxattrAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation) ([]string, error)

ListxattrAt returns all extended attribute names for the file at the given path.

func (*VirtualFilesystem) MkdirAt

func (vfs *VirtualFilesystem) MkdirAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *MkdirOptions) error

MkdirAt creates a directory at the given path.

func (*VirtualFilesystem) MknodAt

func (vfs *VirtualFilesystem) MknodAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *MknodOptions) error

MknodAt creates a file of the given mode at the given path. It returns an error from the syserror package.

func (*VirtualFilesystem) MountAt

func (vfs *VirtualFilesystem) MountAt(ctx context.Context, creds *auth.Credentials, source string, target *PathOperation, fsTypeName string, opts *MountOptions) error

MountAt creates and mounts a Filesystem configured by the given arguments.

func (*VirtualFilesystem) MustRegisterFilesystemType

func (vfs *VirtualFilesystem) MustRegisterFilesystemType(name string, fsType FilesystemType)

MustRegisterFilesystemType is equivalent to RegisterFilesystemType but panics on failure.

func (*VirtualFilesystem) NewMountNamespace

func (vfs *VirtualFilesystem) NewMountNamespace(ctx context.Context, creds *auth.Credentials, source, fsTypeName string, opts *GetFilesystemOptions) (*MountNamespace, error)

NewMountNamespace returns a new mount namespace with a root filesystem configured by the given arguments. A reference is taken on the returned MountNamespace.

func (*VirtualFilesystem) OpenAt

OpenAt returns a FileDescription providing access to the file at the given path. A reference is taken on the returned FileDescription.

func (*VirtualFilesystem) PathnameForGetcwd

func (vfs *VirtualFilesystem) PathnameForGetcwd(ctx context.Context, vfsroot, vd VirtualDentry) (string, error)

PathnameForGetcwd returns an absolute pathname to vd, consistent with Linux's sys_getcwd().

func (*VirtualFilesystem) PathnameWithDeleted

func (vfs *VirtualFilesystem) PathnameWithDeleted(ctx context.Context, vfsroot, vd VirtualDentry) (string, error)

PathnameWithDeleted returns an absolute pathname to vd, consistent with Linux's d_path(). In particular, if vd.Dentry() has been disowned, PathnameWithDeleted appends " (deleted)" to the returned pathname.

func (*VirtualFilesystem) PrepareDeleteDentry

func (vfs *VirtualFilesystem) PrepareDeleteDentry(mntns *MountNamespace, d *Dentry) error

PrepareDeleteDentry must be called before attempting to delete the file represented by d. If PrepareDeleteDentry succeeds, the caller must call AbortDeleteDentry or CommitDeleteDentry depending on the deletion's outcome.

Preconditions: d is a child Dentry.

func (*VirtualFilesystem) PrepareRenameDentry

func (vfs *VirtualFilesystem) PrepareRenameDentry(mntns *MountNamespace, from, to *Dentry) error

PrepareRenameDentry must be called before attempting to rename the file represented by from. If to is not nil, it represents the file that will be replaced or exchanged by the rename. If PrepareRenameDentry succeeds, the caller must call AbortRenameDentry, CommitRenameReplaceDentry, or CommitRenameExchangeDentry depending on the rename's outcome.

Preconditions: from is a child Dentry. If to is not nil, it must be a child Dentry from the same Filesystem.

func (*VirtualFilesystem) ReadlinkAt

func (vfs *VirtualFilesystem) ReadlinkAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation) (string, error)

ReadlinkAt returns the target of the symbolic link at the given path.

func (*VirtualFilesystem) RegisterFilesystemType

func (vfs *VirtualFilesystem) RegisterFilesystemType(name string, fsType FilesystemType) error

RegisterFilesystemType registers the given FilesystemType in vfs with the given name.

func (*VirtualFilesystem) RemovexattrAt

func (vfs *VirtualFilesystem) RemovexattrAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, name string) error

RemovexattrAt removes the given extended attribute from the file at rp.

func (*VirtualFilesystem) RenameAt

func (vfs *VirtualFilesystem) RenameAt(ctx context.Context, creds *auth.Credentials, oldpop, newpop *PathOperation, opts *RenameOptions) error

RenameAt renames the file at oldpop to newpop.

func (*VirtualFilesystem) RmdirAt

func (vfs *VirtualFilesystem) RmdirAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation) error

RmdirAt removes the directory at the given path.

func (*VirtualFilesystem) SetStatAt

func (vfs *VirtualFilesystem) SetStatAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *SetStatOptions) error

SetStatAt changes metadata for the file at the given path.

func (*VirtualFilesystem) SetxattrAt

func (vfs *VirtualFilesystem) SetxattrAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *SetxattrOptions) error

SetxattrAt changes the value associated with the given extended attribute for the file at the given path.

func (*VirtualFilesystem) StatAt

func (vfs *VirtualFilesystem) StatAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *StatOptions) (linux.Statx, error)

StatAt returns metadata for the file at the given path.

func (*VirtualFilesystem) StatFSAt

func (vfs *VirtualFilesystem) StatFSAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation) (linux.Statfs, error)

StatFSAt returns metadata for the filesystem containing the file at the given path.

func (*VirtualFilesystem) SymlinkAt

func (vfs *VirtualFilesystem) SymlinkAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, target string) error

SymlinkAt creates a symbolic link at the given path with the given target.

func (*VirtualFilesystem) SyncAllFilesystems

func (vfs *VirtualFilesystem) SyncAllFilesystems(ctx context.Context) error

SyncAllFilesystems has the semantics of Linux's sync(2).

func (*VirtualFilesystem) UmountAt

func (vfs *VirtualFilesystem) UmountAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *UmountOptions) error

UmountAt removes the Mount at the given path.

func (*VirtualFilesystem) UnlinkAt

func (vfs *VirtualFilesystem) UnlinkAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation) error

UnlinkAt deletes the non-directory file at the given path.

type WriteOptions

type WriteOptions struct {
	// Flags contains flags as specified for pwritev2(2).
	Flags uint32
}

WriteOptions contains options to FileDescription.PWrite(), FileDescriptionImpl.PWrite(), FileDescription.Write(), and FileDescriptionImpl.Write().

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL