Documentation ¶
Index ¶
- Constants
- func BoundReadToFileSize(buf []byte, offset, size uint64) ([]byte, bool)
- func GetFileInfo(name path.Component, node Node) filesystem.FileInfo
- func ReadOnlyDirectoryOpenChildDoesntExist(createAttributes *Attributes) (Leaf, AttributesMask, ChangeInfo, Status)
- func ReadOnlyDirectoryOpenChildWrongFileType(existingOptions *OpenExistingOptions, s Status) (Leaf, AttributesMask, ChangeInfo, Status)
- func Shuffle(data sort.Interface)
- type ApplyAppendOutputPathPersistencyDirectoryNode
- type ApplyGetBazelOutputServiceStat
- type ApplyGetContainingDigests
- type ApplyOpenReadFrozen
- type ApplyReadlink
- type ApplyUploadFile
- type Attributes
- func (a *Attributes) GetChangeID() uint64
- func (a *Attributes) GetDeviceNumber() (filesystem.DeviceNumber, bool)
- func (a *Attributes) GetFileHandle() []byte
- func (a *Attributes) GetFileType() filesystem.FileType
- func (a *Attributes) GetInodeNumber() uint64
- func (a *Attributes) GetLastDataModificationTime() (time.Time, bool)
- func (a *Attributes) GetLinkCount() uint32
- func (a *Attributes) GetPermissions() (Permissions, bool)
- func (a *Attributes) GetSizeBytes() (uint64, bool)
- func (a *Attributes) SetChangeID(changeID uint64) *Attributes
- func (a *Attributes) SetDeviceNumber(deviceNumber filesystem.DeviceNumber) *Attributes
- func (a *Attributes) SetFileHandle(fileHandle []byte) *Attributes
- func (a *Attributes) SetFileType(fileType filesystem.FileType) *Attributes
- func (a *Attributes) SetInodeNumber(inodeNumber uint64) *Attributes
- func (a *Attributes) SetLastDataModificationTime(lastDataModificationTime time.Time) *Attributes
- func (a *Attributes) SetLinkCount(linkCount uint32) *Attributes
- func (a *Attributes) SetPermissions(permissions Permissions) *Attributes
- func (a *Attributes) SetSizeBytes(sizeBytes uint64) *Attributes
- type AttributesMask
- type ByteRangeLock
- type ByteRangeLockSet
- type ByteRangeLockType
- type ByteSliceID
- type CASFileFactory
- func NewBlobAccessCASFileFactory(ctx context.Context, contentAddressableStorage blobstore.BlobAccess, ...) CASFileFactory
- func NewResolvableHandleAllocatingCASFileFactory(base CASFileFactory, allocation StatelessHandleAllocation) CASFileFactory
- func NewStatelessHandleAllocatingCASFileFactory(base CASFileFactory, allocation StatelessHandleAllocation) CASFileFactory
- type ChangeInfo
- type CharacterDeviceFactory
- type Child
- func (Child[TDirectory, TLeaf, TNode]) FromDirectory(directory TDirectory) Child[TDirectory, TLeaf, TNode]
- func (Child[TDirectory, TLeaf, TNode]) FromLeaf(leaf TLeaf) Child[TDirectory, TLeaf, TNode]
- func (c Child[TDirectory, TLeaf, TNode]) GetNode() TNode
- func (c Child[TDirectory, TLeaf, TNode]) GetPair() (TDirectory, TLeaf)
- func (c Child[TDirectory, TLeaf, TNode]) IsSet() bool
- type ChildFilter
- type ChildRemover
- type DigestHandleResolver
- type Directory
- type DirectoryChild
- type DirectoryEntryReporter
- type DirectoryPrepopulatedDirEntry
- type FUSERemovalNotifier
- type FUSERemovalNotifierRegistrar
- type FUSEStatefulHandleAllocator
- type FileAllocator
- type FileReadMonitor
- type FileReadMonitorFactory
- type HandleResolver
- type InitialChild
- type InitialContentsFetcher
- type InitialNode
- type Leaf
- type LeafPrepopulatedDirEntry
- type LinkableLeaf
- type NFSStatefulHandleAllocator
- type Node
- type OpenExistingOptions
- type Permissions
- type PrepopulatedDirectory
- type PrepopulatedDirectoryChild
- type ReadOnlyDirectory
- func (ReadOnlyDirectory) VirtualLink(ctx context.Context, name path.Component, leaf Leaf, requested AttributesMask, ...) (ChangeInfo, Status)
- func (ReadOnlyDirectory) VirtualMkdir(name path.Component, requested AttributesMask, out *Attributes) (Directory, ChangeInfo, Status)
- func (ReadOnlyDirectory) VirtualMknod(ctx context.Context, name path.Component, fileType filesystem.FileType, ...) (Leaf, ChangeInfo, Status)
- func (ReadOnlyDirectory) VirtualRemove(name path.Component, removeDirectory, removeLeaf bool) (ChangeInfo, Status)
- func (ReadOnlyDirectory) VirtualRename(oldName path.Component, newDirectory Directory, newName path.Component) (ChangeInfo, ChangeInfo, Status)
- func (ReadOnlyDirectory) VirtualSetAttributes(ctx context.Context, in *Attributes, requested AttributesMask, out *Attributes) Status
- func (ReadOnlyDirectory) VirtualSymlink(ctx context.Context, pointedTo []byte, linkName path.Component, ...) (Leaf, ChangeInfo, Status)
- type ResolvableDigestHandleAllocator
- type ResolvableHandleAllocation
- type ResolvableHandleAllocator
- type ShareMask
- type Sorter
- type StatefulDirectoryHandle
- type StatefulHandleAllocation
- type StatefulHandleAllocator
- type StatelessHandleAllocation
- type StatelessHandleAllocator
- type Status
- type StringMatcher
- type SymlinkFactory
- type UserSettableSymlink
- func (f *UserSettableSymlink) CheckReadiness(ctx context.Context, request *emptypb.Empty) (*emptypb.Empty, error)
- func (f *UserSettableSymlink) InstallTemporaryDirectory(ctx context.Context, request *tmp_installer.InstallTemporaryDirectoryRequest) (*emptypb.Empty, error)
- func (UserSettableSymlink) Link() Status
- func (UserSettableSymlink) Unlink()
- func (UserSettableSymlink) VirtualAllocate(off, size uint64) Status
- func (UserSettableSymlink) VirtualApply(data any) bool
- func (UserSettableSymlink) VirtualClose(shareAccess ShareMask)
- func (f *UserSettableSymlink) VirtualGetAttributes(ctx context.Context, requested AttributesMask, attributes *Attributes)
- func (UserSettableSymlink) VirtualOpenSelf(ctx context.Context, shareAccess ShareMask, options *OpenExistingOptions, ...) Status
- func (UserSettableSymlink) VirtualRead(buf []byte, offset uint64) (int, bool, Status)
- func (f *UserSettableSymlink) VirtualReadlink(ctx context.Context) ([]byte, Status)
- func (UserSettableSymlink) VirtualSeek(offset uint64, regionType filesystem.RegionType) (*uint64, Status)
- func (f *UserSettableSymlink) VirtualSetAttributes(ctx context.Context, in *Attributes, requested AttributesMask, out *Attributes) Status
- func (UserSettableSymlink) VirtualWrite(buf []byte, off uint64) (int, Status)
Constants ¶
const ( // ImplicitDirectoryLinkCount is the value that should be // assigned to fuse.attr.Nlink for directory nodes for which the // directory contents are not defined explicitly. These may be // directories that are lazy-loading, or have an infinite number // of children due to them being defined programmatically. // // It is important that we return a link count lower than two // for these directories. Tools like GNU find(1) rely on an // accurate link count to rule out the existence of child // directories. A link count below two instructs them to disable // such optimizations, forcing them to read directory listings. // See the "-noleaf" option in find(1)'s man page for details. // // File systems such as btrfs also set the link count of // directories to one. ImplicitDirectoryLinkCount uint32 = 1 // EmptyDirectoryLinkCount is the value that should be assigned // to fuse.attr.Nlink for directory nodes that do not have any // child directories. EmptyDirectoryLinkCount uint32 = 2 )
const StatelessLeafLinkCount = 9999
StatelessLeafLinkCount is the value that should be assigned to fuse.Attr.Nlink for leaf nodes that don't track an explicit link count, such as files backed by the Content Addressable Storage (CAS).
The Linux kernel doesn't treat fuse.Attr.Nlink as an opaque value. Its value gets stored in the kernel inode structure's i_nlink field. This cached value may later be incremented and decremented inside fuse_link() and fuse_unlink(), meaning that it may reach zero. Once zero, the kernel thinks the file is unlinked, causing future link() calls to fail.
This means that the value of fuse.Attr.Nlink should ideally reflect the true number of paths under which these files are visible. For stateless files that is impossible to achieve, as they may appear in an arbitrary number of places that aren't known up front. Solve this by using a constant value that is sufficiently high for most use cases.
References: - https://github.com/torvalds/linux/blob/01c70267053d6718820ac0902d8823d5dd2a6adb/fs/fuse/inode.c#L161 - https://github.com/torvalds/linux/blob/01c70267053d6718820ac0902d8823d5dd2a6adb/fs/fuse/dir.c#L874 - https://github.com/torvalds/linux/blob/01c70267053d6718820ac0902d8823d5dd2a6adb/fs/fuse/dir.c#L726 - https://github.com/torvalds/linux/blob/01c70267053d6718820ac0902d8823d5dd2a6adb/fs/namei.c#L4066-L4067
Variables ¶
This section is empty.
Functions ¶
func BoundReadToFileSize ¶
BoundReadToFileSize is a helper function for implementations of VirtualRead() to limit the read size to the actual file size.
func GetFileInfo ¶
func GetFileInfo(name path.Component, node Node) filesystem.FileInfo
GetFileInfo extracts the attributes of a node and returns it in the form of a FileInfo object.
func ReadOnlyDirectoryOpenChildDoesntExist ¶
func ReadOnlyDirectoryOpenChildDoesntExist(createAttributes *Attributes) (Leaf, AttributesMask, ChangeInfo, Status)
ReadOnlyDirectoryOpenChildDoesntExist is a helper function for implementing Directory.VirtualOpenChild() for read-only directories. It can be used to obtain return values in case the directory doesn't contains any file under a given name.
func ReadOnlyDirectoryOpenChildWrongFileType ¶
func ReadOnlyDirectoryOpenChildWrongFileType(existingOptions *OpenExistingOptions, s Status) (Leaf, AttributesMask, ChangeInfo, Status)
ReadOnlyDirectoryOpenChildWrongFileType is a helper function for implementing Directory.VirtualOpenChild() for read-only directories. It can be used to obtain return values in case the directory already contains a file under a given name.
Types ¶
type ApplyAppendOutputPathPersistencyDirectoryNode ¶
type ApplyAppendOutputPathPersistencyDirectoryNode struct { // Inputs. Directory *outputpathpersistency.Directory Name path.Component }
ApplyAppendOutputPathPersistencyDirectoryNode is an operation for VirtualApply that appends a FileNode or SymlinkNode entry to a Directory message that is used to persist the state of a Bazel Output Service output path to disk.
type ApplyGetBazelOutputServiceStat ¶
type ApplyGetBazelOutputServiceStat struct { // Inputs. DigestFunction *digest.Function // Outputs. Stat *bazeloutputservice.BatchStatResponse_Stat Err error }
ApplyGetBazelOutputServiceStat is an operation for VirtualApply that returns the status of the leaf node in the form of a Status message that is used by the Bazel Output Service protocol.
type ApplyGetContainingDigests ¶
type ApplyGetContainingDigests struct { // Inputs. Context context.Context // Outputs. ContainingDigests digest.Set Err error }
ApplyGetContainingDigests is an operation for VirtualApply that returns a set of digests of objects in the Content Addressable Storage that back the contents of this file.
The set returned by this function may be passed to ContentAddressableStorage.FindMissingBlobs() to check whether the file still exists in its entirety, and to prevent that the file is removed in the nearby future.
type ApplyOpenReadFrozen ¶
type ApplyOpenReadFrozen struct { // Inputs. WritableFileDelay <-chan struct{} // Outputs. Reader filesystem.FileReader Err error }
ApplyOpenReadFrozen is an operation for VirtualApply that opens a regular file for reading. The file's contents are guaranteed to be immutable as long as the file is kept open.
If the file is still opened for writing through the virtual file system, implementations should wait for the file to be closed to ensure that all data is flushed from the page cache. The WritableFileDelay channel can be used to place a bound on the maximum amount of time to wait.
type ApplyReadlink ¶
ApplyReadlink is an operation for VirtualApply that returns the target of a symbolic link in parsed form.
type ApplyUploadFile ¶
type ApplyUploadFile struct { // Inputs. Context context.Context ContentAddressableStorage blobstore.BlobAccess DigestFunction digest.Function WritableFileUploadDelay <-chan struct{} // Outputs. Digest digest.Digest Err error }
ApplyUploadFile is an operation for VirtualApply that uploads the contents of a file into the Content Addressable Storage and returns the resulting object's digest.
type Attributes ¶
type Attributes struct {
// contains filtered or unexported fields
}
Attributes of a file, normally requested through stat() or readdir(). A bitmask is used to track which attributes are set.
func (*Attributes) GetChangeID ¶
func (a *Attributes) GetChangeID() uint64
GetChangeID returns the change ID, which clients can use to determine if file data, directory contents, or attributes of the node have changed.
func (*Attributes) GetDeviceNumber ¶
func (a *Attributes) GetDeviceNumber() (filesystem.DeviceNumber, bool)
GetDeviceNumber returns the raw device number (st_rdev).
func (*Attributes) GetFileHandle ¶
func (a *Attributes) GetFileHandle() []byte
GetFileHandle returns an identifier of the file that contains sufficient information to be able to resolve it at a later point in time.
func (*Attributes) GetFileType ¶
func (a *Attributes) GetFileType() filesystem.FileType
GetFileType returns the file type (upper 4 bits of st_mode).
func (*Attributes) GetInodeNumber ¶
func (a *Attributes) GetInodeNumber() uint64
GetInodeNumber returns the inode number (st_ino).
func (*Attributes) GetLastDataModificationTime ¶
func (a *Attributes) GetLastDataModificationTime() (time.Time, bool)
GetLastDataModificationTime returns the last data modification time (st_mtim).
func (*Attributes) GetLinkCount ¶
func (a *Attributes) GetLinkCount() uint32
GetLinkCount returns the link count (st_nlink).
func (*Attributes) GetPermissions ¶
func (a *Attributes) GetPermissions() (Permissions, bool)
GetPermissions returns the mode (lowest 12 bits of st_mode).
func (*Attributes) GetSizeBytes ¶
func (a *Attributes) GetSizeBytes() (uint64, bool)
GetSizeBytes returns the file size (st_size).
func (*Attributes) SetChangeID ¶
func (a *Attributes) SetChangeID(changeID uint64) *Attributes
SetChangeID sets the change ID, which clients can use to determine if file data, directory contents, or attributes of the node have changed.
func (*Attributes) SetDeviceNumber ¶
func (a *Attributes) SetDeviceNumber(deviceNumber filesystem.DeviceNumber) *Attributes
SetDeviceNumber sets the raw device number (st_rdev).
func (*Attributes) SetFileHandle ¶
func (a *Attributes) SetFileHandle(fileHandle []byte) *Attributes
SetFileHandle sets an identifier of the file that contains sufficient information to be able to resolve it at a later point in time.
func (*Attributes) SetFileType ¶
func (a *Attributes) SetFileType(fileType filesystem.FileType) *Attributes
SetFileType sets the file type (upper 4 bits of st_mode).
func (*Attributes) SetInodeNumber ¶
func (a *Attributes) SetInodeNumber(inodeNumber uint64) *Attributes
SetInodeNumber sets the inode number (st_ino).
func (*Attributes) SetLastDataModificationTime ¶
func (a *Attributes) SetLastDataModificationTime(lastDataModificationTime time.Time) *Attributes
SetLastDataModificationTime sets the last data modification time (st_mtim).
func (*Attributes) SetLinkCount ¶
func (a *Attributes) SetLinkCount(linkCount uint32) *Attributes
SetLinkCount sets the link count (st_nlink).
func (*Attributes) SetPermissions ¶
func (a *Attributes) SetPermissions(permissions Permissions) *Attributes
SetPermissions sets the mode (lowest 12 bits of st_mode).
func (*Attributes) SetSizeBytes ¶
func (a *Attributes) SetSizeBytes(sizeBytes uint64) *Attributes
SetSizeBytes sets the file size (st_size).
type AttributesMask ¶
type AttributesMask uint32
AttributesMask is a bitmask of status attributes that need to be requested through Node.VirtualGetAttributes().
const ( // AttributesMaskChangeID requests the change ID, which clients // can use to determine if file data, directory contents, or // attributes of the node have changed. AttributesMaskChangeID AttributesMask = 1 << iota // AttributesMaskDeviceNumber requests the raw device number // (st_rdev). AttributesMaskDeviceNumber // AttributesMaskFileHandle requests an identifier of the file // that contains sufficient information to be able to resolve it // at a later point in time. AttributesMaskFileHandle // AttributesMaskFileType requests the file type (upper 4 bits // of st_mode). AttributesMaskFileType // AttributesMaskInodeNumber requests the inode number (st_ino). AttributesMaskInodeNumber // AttributesMaskLastDataModificationTime requests the last data // modification time (st_mtim). AttributesMaskLastDataModificationTime // AttributesMaskLinkCount requests the link count (st_nlink). AttributesMaskLinkCount // AttributesMaskPermissions requests the permissions (lowest 12 // bits of set_mode). AttributesMaskPermissions // AttributesMaskSizeBytes requests the file size (st_size). AttributesMaskSizeBytes )
type ByteRangeLock ¶
type ByteRangeLock[Owner comparable] struct { Start uint64 End uint64 Owner Owner Type ByteRangeLockType }
ByteRangeLock holds information on a lock held on a non-empty range of bytes. Each lock has an owner associated with it. This field is only checked for equality, allowing it to merge adjacent or overlapping locks held by the same owner.
type ByteRangeLockSet ¶
type ByteRangeLockSet[Owner comparable] struct { // contains filtered or unexported fields }
ByteRangeLockSet is a set for ByteRangeLocks applied against the same file. The set is modeled as a linked list, where entries are sorted by starting address. All entries describe disjoint non-empty ranges of bytes, except for shared locks with distinct owners.
func (*ByteRangeLockSet[Owner]) Initialize ¶
func (ls *ByteRangeLockSet[Owner]) Initialize()
Initialize the ByteRangeLockSet, so that it does not contain any locks.
func (*ByteRangeLockSet[Owner]) Set ¶
func (ls *ByteRangeLockSet[Owner]) Set(lProvided *ByteRangeLock[Owner]) int
Set a byte range to a given lock. Calls to this method must generally be preceded by calls to Test(), as it is assumed the lock to be inserted does not conflict with the locks that are currently held.
This method returns the increase (positive) or decrease (negative) of the number of entries in the set. This can be used by the caller to determine when the owner of the lock can be released.
func (*ByteRangeLockSet[Owner]) Test ¶
func (ls *ByteRangeLockSet[Owner]) Test(lTest *ByteRangeLock[Owner]) *ByteRangeLock[Owner]
Test whether a new lock to be inserted does not conflict with any of the other locks registered in the set.
type ByteRangeLockType ¶
type ByteRangeLockType int
ByteRangeLockType is an enumeration that controls what kind of lock needs to be acquired.
const ( // ByteRangeLockTypeUnlocked indicates that a byte range should // be unlocked. This value can only be provided to Set(); not // Test(). It is equivalent to POSIX's F_UNLCK. ByteRangeLockTypeUnlocked ByteRangeLockType = iota // ByteRangeLockTypeLockedExclusive indicates that a byte range // should be locked exclusively for writing. It is equivalent to // POSIX's F_WRLCK. ByteRangeLockTypeLockedExclusive // should be locked shared for reading. It is equivalent to // F_RDLCK. ByteRangeLockTypeLockedShared )
type ByteSliceID ¶
type ByteSliceID []byte
ByteSliceID is a helper type for consumers of StatelessHandleAllocator and ResolvableHandleAllocator. It uses the contents of a byte slice as an object ID. The byte slice will be prefixed with its own length, so that no ambiguity exists if allocators are nested.
type CASFileFactory ¶
type CASFileFactory interface {
LookupFile(digest digest.Digest, isExecutable bool, readMonitor FileReadMonitor) LinkableLeaf
}
CASFileFactory is a factory type for files whose contents correspond with an object stored in the Content Addressable Storage (CAS).
func NewBlobAccessCASFileFactory ¶
func NewBlobAccessCASFileFactory(ctx context.Context, contentAddressableStorage blobstore.BlobAccess, errorLogger util.ErrorLogger) CASFileFactory
NewBlobAccessCASFileFactory creates a CASFileFactory that can be used to create FUSE files that are directly backed by BlobAccess. Files created by this factory are entirely immutable; it is only possible to read their contents.
func NewResolvableHandleAllocatingCASFileFactory ¶
func NewResolvableHandleAllocatingCASFileFactory(base CASFileFactory, allocation StatelessHandleAllocation) CASFileFactory
NewResolvableHandleAllocatingCASFileFactory creates a decorator for CASFileFactory that creates read-only files for files stored in the Content Addressable Storage that have a stateless handle associated with them.
This decorator is intended to be used in places where CASFileFactory is used to hand out files with an indefinite lifetime, such as bb_clientd's "cas" directory. File handles will be larger, as the hash, size and executable bit of of the file will be stored in the file handle.
func NewStatelessHandleAllocatingCASFileFactory ¶
func NewStatelessHandleAllocatingCASFileFactory(base CASFileFactory, allocation StatelessHandleAllocation) CASFileFactory
NewStatelessHandleAllocatingCASFileFactory creates a decorator for CASFileFactory that creates read-only files for files stored in the Content Addressable Storage that have a stateless handle associated with them.
This decorator is intended to be used in places where CASFileFactory is used to place files in mutable directories that properly track lifetimes of files. By making these files stateless, as opposed to resolvable, implementations of HandleAllocator may deduplicate multiple instances of the same file in the file system.
type ChangeInfo ¶
ChangeInfo contains a pair of change IDs of a directory, before and after performing a directory mutating operation. This information needs to be returned by various NFSv4 operations.
type CharacterDeviceFactory ¶
type CharacterDeviceFactory interface {
LookupCharacterDevice(deviceNumber filesystem.DeviceNumber) LinkableLeaf
}
CharacterDeviceFactory is a factory type for character devices. Character devices are immutable files; it is not possible to change the device after it has been created.
var BaseCharacterDeviceFactory CharacterDeviceFactory = baseCharacterDeviceFactory{}
BaseCharacterDeviceFactory can be used to create simple immutable character device nodes.
func NewHandleAllocatingCharacterDeviceFactory ¶
func NewHandleAllocatingCharacterDeviceFactory(base CharacterDeviceFactory, allocation ResolvableHandleAllocation) CharacterDeviceFactory
NewHandleAllocatingCharacterDeviceFactory creates a decorator for CharacterDeviceFactory that creates character devices that have a handle associated with them.
Because device numbers are small, this implementation uses a resolvable handle allocator, meaning that the major and minor number of the device are stored in the file handle.
type Child ¶
type Child[TDirectory any, TLeaf any, TNode any] struct { // contains filtered or unexported fields }
Child is a variant type that either contains a directory or leaf object.
TODO: In principle it should be possible to eliminate the 'kind' field, if it weren't for the fact that we can't compare TDirectory and TLeaf against nil. There is no nullable constraint. https://github.com/golang/go/issues/53656
func (Child[TDirectory, TLeaf, TNode]) FromDirectory ¶
func (Child[TDirectory, TLeaf, TNode]) FromDirectory(directory TDirectory) Child[TDirectory, TLeaf, TNode]
FromDirectory creates a Child that contains a directory.
func (Child[TDirectory, TLeaf, TNode]) GetNode ¶
func (c Child[TDirectory, TLeaf, TNode]) GetNode() TNode
GetNode returns the value of the child as a single object, making it possible to call into methods that are both provided by the directory and leaf types.
type ChildFilter ¶
type ChildFilter func(node InitialChild, remove ChildRemover) bool
ChildFilter is a callback that is invoked by PrepopulatedDirectory.FilterChildren() for each of the children underneath the current directory hierarchy.
For each of the children, an InitialChild object is provided that describes the contents of that file or directory. In addition to that, a callback is provided that can remove the file or the contents of the directory. This callback may be invoked synchronously or asynchronously, potentially after FilterChildren() has completed.
The boolean return value of this function signals whether traversal should continue. When false, traversal will stop immediately.
type ChildRemover ¶
type ChildRemover func() error
ChildRemover is a callback that is provided to ChildFilter to remove the provided file or contents of the provided directory.
type DigestHandleResolver ¶
type DigestHandleResolver func(blobDigest digest.Digest, remainder io.ByteReader) (DirectoryChild, Status)
DigestHandleResolver is a handle resolver that needs to be implemented by users of ResolvableDigestHandleAllocator. This callback is responsible for looking up a file or directory that corresponds to a given REv2 digest that was reobtained from a file handle.
type Directory ¶
type Directory interface { Node // VirtualOpenChild opens a regular file within the directory. // // When createAttributes is nil, this method will fail with // StatusErrNoEnt if the file does not exist. When not nil, a // file will be created. // // When existingOptions is nil, this method will fail with // StatusErrExist if the file already exists. When not nil, an // existing file will be opened. // // Either one or both of createAttributes and existingOptions // need to be provided. VirtualOpenChild(ctx context.Context, name path.Component, shareAccess ShareMask, createAttributes *Attributes, existingOptions *OpenExistingOptions, requested AttributesMask, openedFileAttributes *Attributes) (Leaf, AttributesMask, ChangeInfo, Status) // VirtualLink links an existing file into the directory. VirtualLink(ctx context.Context, name path.Component, leaf Leaf, requested AttributesMask, attributes *Attributes) (ChangeInfo, Status) // VirtualLookup obtains the inode corresponding with a child // stored within the directory. // // TODO: Can't use DirectoryChild in the return type here, due to // https://github.com/golang/go/issues/50259. VirtualLookup(ctx context.Context, name path.Component, requested AttributesMask, out *Attributes) (Child[Directory, Leaf, Node], Status) // VirtualMkdir creates an empty directory within the current // directory. VirtualMkdir(name path.Component, requested AttributesMask, attributes *Attributes) (Directory, ChangeInfo, Status) // VirtualMknod creates a character FIFO or UNIX domain socket // within the current directory. VirtualMknod(ctx context.Context, name path.Component, fileType filesystem.FileType, requested AttributesMask, attributes *Attributes) (Leaf, ChangeInfo, Status) // VirtualReadDir reports files and directories stored within // the directory. VirtualReadDir(ctx context.Context, firstCookie uint64, requested AttributesMask, reporter DirectoryEntryReporter) Status // VirtualRename renames a file stored in the current directory, // potentially moving it to another directory. VirtualRename(oldName path.Component, newDirectory Directory, newName path.Component) (ChangeInfo, ChangeInfo, Status) // VirtualRemove removes an empty directory or leaf node stored // within the current directory. Depending on the parameters, // this method behaves like rmdir(), unlink() or a mixture of // the two. The latter is needed by NFSv4. VirtualRemove(name path.Component, removeDirectory, removeLeaf bool) (ChangeInfo, Status) // VirtualSymlink creates a symbolic link within the current // directory. VirtualSymlink(ctx context.Context, pointedTo []byte, linkName path.Component, requested AttributesMask, attributes *Attributes) (Leaf, ChangeInfo, Status) }
Directory node that is exposed through FUSE using SimpleRawFileSystem, or through NFSv4. The names of all of these operations are prefixed with 'Virtual' to ensure they don't collide with filesystem.Directory.
func NewStaticDirectory ¶
func NewStaticDirectory(directories map[path.Component]DirectoryChild) Directory
NewStaticDirectory creates a Directory that contains a hardcoded list of child files or directories. The contents of this directory are immutable.
type DirectoryChild ¶
DirectoryChild is either a Directory or a Leaf, as returned by Directory.VirtualLookup().
type DirectoryEntryReporter ¶
type DirectoryEntryReporter interface { // TODO: Can't use DirectoryChild in the arguments here, due to // https://github.com/golang/go/issues/50259. ReportEntry(nextCookie uint64, name path.Component, child Child[Directory, Leaf, Node], attributes *Attributes) bool }
DirectoryEntryReporter is used by VirtualReadDir() to report individual directory entries. These methods may be called while locks on the underlying directory are held. This means that it's not safe to call methods of the child directory, as that could cause deadlocks.
type DirectoryPrepopulatedDirEntry ¶
type DirectoryPrepopulatedDirEntry struct { Child PrepopulatedDirectory Name path.Component }
DirectoryPrepopulatedDirEntry contains information about a directory node that is stored in a PrepopulatedDirectory.
type FUSERemovalNotifier ¶
FUSERemovalNotifier is a callback method that can be registered to report the removal of files from stateful directories.
type FUSERemovalNotifierRegistrar ¶
type FUSERemovalNotifierRegistrar func(removalNotifier FUSERemovalNotifier)
FUSERemovalNotifierRegistrar has the same signature as FUSEStatefulHandleAllocator.RegisterRemovalNotifier(). It has been added to aid testing.
type FUSEStatefulHandleAllocator ¶
type FUSEStatefulHandleAllocator struct {
// contains filtered or unexported fields
}
FUSEStatefulHandleAllocator creates a handle allocator for the purpose of exposing the virtual file system through FUSE. It is responsible for decorating all files in the file system, so that they have inode numbers and link counts. Inode numbers are unique for stateful (mutable) files, while they are identical for stateless files that share the same identifiers, meaning they can be deduplicated by the kernel.
The FUSE protocol is stateful, in the sense that the kernel and the userspace service share state on which nodes in the file system have been resolved. The kernel will never issue requests against objects that have not been resolved yet, or for which the kernel has issued a FORGET operation. This means that this handle allocator does not need to provide any mechanism for resolving arbitrary files present in the file system, making its implementation simple. There is thus no distinction between stateless and resolvable files.
func NewFUSEHandleAllocator ¶
func NewFUSEHandleAllocator(randomNumberGenerator random.ThreadSafeGenerator) *FUSEStatefulHandleAllocator
NewFUSEHandleAllocator creates a new FUSEStatefulHandleAllocator.
func (*FUSEStatefulHandleAllocator) New ¶
func (hr *FUSEStatefulHandleAllocator) New() StatefulHandleAllocation
New creates a new stateful handle allocation.
func (*FUSEStatefulHandleAllocator) RegisterRemovalNotifier ¶
func (hr *FUSEStatefulHandleAllocator) RegisterRemovalNotifier(removalNotifier FUSERemovalNotifier)
RegisterRemovalNotifier adds a new file removal notifier to the handle allocator. Any future calls to Release() against DirectoryHandles returned by this handle allocator will call into the FUSERemovalNotifier, providing it the inode number of the parent directory.
This method is used by the FUSE server to register a callback that sends "entry notify" events to the kernel, causing the directory entry to be removed from the kernel's cache.
type FileAllocator ¶
type FileAllocator interface {
NewFile(isExecutable bool, size uint64, shareAccess ShareMask) (LinkableLeaf, Status)
}
FileAllocator is called into by InMemoryPrepopulatedDirectory to create new files within the file system. Such files could either be stored in memory, on disk, remotely, etc.
Files returned by this interface should have a link count of 1, and are opened using the provided share access mask.
func NewHandleAllocatingFileAllocator ¶
func NewHandleAllocatingFileAllocator(base FileAllocator, allocator StatefulHandleAllocator) FileAllocator
NewHandleAllocatingFileAllocator creates a decorator for FileAllocator that creates mutable files that have a stateful handle associated with them. This gives ever mutable file its own inode number and link count.
func NewPoolBackedFileAllocator ¶
func NewPoolBackedFileAllocator(pool re_filesystem.FilePool, errorLogger util.ErrorLogger) FileAllocator
NewPoolBackedFileAllocator creates an allocator for a leaf node that may be stored in an PrepopulatedDirectory, representing a mutable regular file. All operations to mutate file contents (reads, writes and truncations) are forwarded to a file obtained from a FilePool.
When the file becomes unreachable (i.e., both its link count and open file descriptor count reach zero), Close() is called on the underlying backing file descriptor. This may be used to request deletion from underlying storage.
type FileReadMonitor ¶
type FileReadMonitor func()
FileReadMonitor is used by the regular files created through the InitialContentsFetcher to indicate that one or more calls against VirtualRead() have occurred. This is used by AccessMonitoringInitialContentsFetcher to monitor file access.
type FileReadMonitorFactory ¶
type FileReadMonitorFactory func(name path.Component) FileReadMonitor
FileReadMonitorFactory is a factory type for FileReadMonitor that is provided to the InitialContentsFetcher, so that the InitialContentsFetcher can attach the resulting monitors to any files that are returned.
If this function returns nil, no monitor is attached to the file.
type HandleResolver ¶
type HandleResolver func(r io.ByteReader) (DirectoryChild, Status)
HandleResolver is a method that is used by ResolvableHandleAllocator to reconstruct files based on the identifiers provided to New().
TODO: Implementations of this method must currently make sure that directories and leaves that are returned are decorated with a handle allocation. Can't we let implementations of ResolvableHandleAllocator do this? That way resolvers may remain simple.
type InitialChild ¶
type InitialChild = Child[InitialContentsFetcher, LinkableLeaf, InitialNode]
InitialChild is the value type of the map of directory entries returned by InitialContentsFetcher.FetchContents(). Either Directory or Leaf is set, but not both.
type InitialContentsFetcher ¶
type InitialContentsFetcher interface { InitialNode FetchContents(fileReadMonitorFactory FileReadMonitorFactory) (map[path.Component]InitialChild, error) }
InitialContentsFetcher is called into by PrepopulatedDirectory when a directory whose contents need to be instantiated lazily is accessed. The results returned by FetchContents() are used to populate the directory.
FetchContents() should be called until it succeeds at most once. It may be possible FetchContents() is never called. This may happen if the directory in question is never accessed.
var EmptyInitialContentsFetcher InitialContentsFetcher = emptyInitialContentsFetcher{}
EmptyInitialContentsFetcher is an instance of InitialContentsFetcher that yields no children. It can be used in case an empty directory needs to be created.
func NewAccessMonitoringInitialContentsFetcher ¶
func NewAccessMonitoringInitialContentsFetcher(base InitialContentsFetcher, rootDirectoryMonitor access.UnreadDirectoryMonitor) InitialContentsFetcher
NewAccessMonitoringInitialContentsFetcher decorates an InitialContentsFetcher, so that any read access to files and directories is reported to an UnreadDirectoryMonitor. This can be used to create file system access profiles of build actions.
func NewCASInitialContentsFetcher ¶
func NewCASInitialContentsFetcher(ctx context.Context, directoryWalker cas.DirectoryWalker, casFileFactory CASFileFactory, symlinkFactory SymlinkFactory, digestFunction digest.Function) InitialContentsFetcher
NewCASInitialContentsFetcher creates an InitialContentsFetcher that lazily instantiates a full directory hierarchy based on directory objects stored in the Content Addressable Storage (CAS).
Upon request, it loads the root directory of the tree and converts all of the children to either additional InitialContentFetchers (directories), FileBackedFiles (regular files) or Symlinks (symbolic links).
type InitialNode ¶
type InitialNode interface { // VirtualApply can be used to perform implementation defined // operations against files and directories. VirtualApply(data any) bool }
InitialNode contains the common set of operations that can be applied against files and directories returned by InitialContentsFetcher.FetchContents().
type Leaf ¶
type Leaf interface { Node VirtualAllocate(off, size uint64) Status VirtualSeek(offset uint64, regionType filesystem.RegionType) (*uint64, Status) VirtualOpenSelf(ctx context.Context, shareAccess ShareMask, options *OpenExistingOptions, requested AttributesMask, attributes *Attributes) Status VirtualRead(buf []byte, offset uint64) (n int, eof bool, s Status) VirtualReadlink(ctx context.Context) ([]byte, Status) VirtualClose(shareAccess ShareMask) VirtualWrite(buf []byte, offset uint64) (int, Status) }
Leaf node that is exposed through FUSE using SimpleRawFileSystem, or through NFSv4. Examples of leaf nodes are regular files, sockets, FIFOs, symbolic links and devices.
TODO: Should all methods take an instance of Context?
type LeafPrepopulatedDirEntry ¶
type LeafPrepopulatedDirEntry struct { Child LinkableLeaf Name path.Component }
LeafPrepopulatedDirEntry contains information about a leaf node that is stored in a PrepopulatedDirectory.
type LinkableLeaf ¶
type LinkableLeaf interface { Leaf InitialNode // Operations called into by implementations of // PrepopulatedDirectory. The Link() operation may fail, for the // reason that Directory.VirtualLink() may be called on leaf // nodes that have been removed concurrently. Link() Status Unlink() }
LinkableLeaf objects are non-directory nodes that can be placed in a PrepopulatedDirectory.
func NewSpecialFile ¶
func NewSpecialFile(fileType filesystem.FileType, deviceNumber *filesystem.DeviceNumber) LinkableLeaf
NewSpecialFile creates a node that may be used as a character device, block device, FIFO or UNIX domain socket. Nodes of these types are mere placeholders. The kernel is responsible for capturing calls to open() and connect().
type NFSStatefulHandleAllocator ¶
type NFSStatefulHandleAllocator struct {
// contains filtered or unexported fields
}
NFSStatefulHandleAllocator creates a handle allocator for the purpose of exposing the virtual file system through NFS. It is responsible for decorating all files in the file system, so that they have file handles, inode numbers and link counts. File handles and inode numbers are unique for stateful (mutable) files, while they are identical for stateless files that share the same identifiers, meaning they can be deduplicated by the kernel.
The NFS protocol is stateless, in the sense that the client and server share no state on which nodes in the file system have been resolved. The client does not inform the server that it has released files from its cache. This means that the server needs to be able to resolve all file handles that are either still present in the file system or are still opened by the client. This handle allocator is capable of only doing the former. The latter can be supported at a higher level.
To work well with infinitely big directory structures (e.g., bb_clientd's "cas" directory), this implementation makes use of the handle resolver function provided to AsResolvableAllocator(). Instead of tracking these nodes explicitly, it generates longer file handles that have the value provided to ResolvableHandleAllocator.New() as a suffix, making it possible to regenerate these nodes on the fly.
func NewNFSHandleAllocator ¶
func NewNFSHandleAllocator(randomNumberGenerator random.SingleThreadedGenerator) *NFSStatefulHandleAllocator
NewNFSHandleAllocator creates a new NFSStatefulHandleAllocator that does not have any resolvable objects.
func (*NFSStatefulHandleAllocator) New ¶
func (hr *NFSStatefulHandleAllocator) New() StatefulHandleAllocation
New creates a new stateful handle allocation.
func (*NFSStatefulHandleAllocator) ResolveHandle ¶
func (hr *NFSStatefulHandleAllocator) ResolveHandle(r io.ByteReader) (DirectoryChild, Status)
ResolveHandle resolves a directory or leaf object that corresponds with a file handle previously returned by Attributes.GetFileHandle().
Only files that are linked into the file system are guaranteed to be resolvable. Files that have been unlinked, but are still opened have to be tracked at a higher level.
type Node ¶
type Node interface { VirtualGetAttributes(ctx context.Context, requested AttributesMask, attributes *Attributes) VirtualSetAttributes(ctx context.Context, in *Attributes, requested AttributesMask, attributes *Attributes) Status // VirtualApply can be used to send data between backing nodes. Returns true // if the request was intercepted. VirtualApply(data any) bool }
Node is the intersection between Directory and Leaf. These are the operations that can be applied to both kinds of objects.
type OpenExistingOptions ¶
type OpenExistingOptions struct {
Truncate bool
}
OpenExistingOptions contains options that describe what should happen with a file when opened. The Truncate option corresponds to open()'s O_TRUNC option. This option has no effect on freshly created files, as those are always empty.
func (*OpenExistingOptions) ToAttributesMask ¶
func (o *OpenExistingOptions) ToAttributesMask() (m AttributesMask)
ToAttributesMask converts open options to an AttributeMask, indicating which file attributes were affected by the operation.
type Permissions ¶
type Permissions uint8
Permissions of a file. Unlike regular UNIX file system, no distinction is made between owner, group and all permissions. This is because the virtual file system is effectively single user.
const ( // PermissionsRead indicates that file contents may be read, or // that files in a directory may be listed. PermissionsRead Permissions = 1 << iota // PermissionsWrite indicates that file contents may be written // to, or that files in a directory may be added, removed or // renamed. PermissionsWrite // PermissionsExecute indicates that a file is executable, or // that files in a directory may be looked up. PermissionsExecute )
func NewPermissionsFromMode ¶
func NewPermissionsFromMode(m uint32) (p Permissions)
NewPermissionsFromMode creates a set of permissions from a traditional UNIX style mode.
func (Permissions) ToMode ¶
func (p Permissions) ToMode() (m uint32)
ToMode converts a set of permissions to a traditional UNIX style mode. The permissions for the owner, group and all will be identical.
type PrepopulatedDirectory ¶
type PrepopulatedDirectory interface { Directory // LookupChild() looks up a file or directory contained in a // PrepopulatedDirectory. This method is similar to // VirtualLookup(), except that it returns the native types // managed by PrepopulatedDirectory. // // TODO: Can't use PrepopulatedDirectoryChild in the return type // here, due to https://github.com/golang/go/issues/50259. LookupChild(name path.Component) (Child[PrepopulatedDirectory, LinkableLeaf, Node], error) // LookupAllChildren() looks up all files and directories // contained in a PrepopulatedDirectory. This method is similar // to VirtualReadDir(), except that it returns the native types // managed by PrepopulatedDirectory. Entries are returned in // alphabetical order. LookupAllChildren() ([]DirectoryPrepopulatedDirEntry, []LeafPrepopulatedDirEntry, error) // CreateChildren() creates one or more files or directories in // the current directory. // // If the overwrite flag is set, existing files and directories // will be replaced. If the overwrite flag is not set, the call // will fail if one or more entries already exist. No changes // will be made to the directory in that case. CreateChildren(children map[path.Component]InitialChild, overwrite bool) error // CreateAndEnterPrepopulatedDirectory() is similar to // LookupChild(), except that it creates the specified directory // if it does not yet exist. If a file already exists, it will // be removed. CreateAndEnterPrepopulatedDirectory(name path.Component) (PrepopulatedDirectory, error) // RemoveAllChildren() removes all files and directories // contained in the current directory. // // This method is identical to the one filesystem.Directory, // except that the forbidNewChildren flag may be set to // permanently mark the directory in such a way that no further // files may be added. When called on the root directory, all // resources associated with the directory hierarchy will be // released. RemoveAllChildren(forbidNewChildren bool) error // InstallHooks sets up hooks for creating files and logging // errors that occur under the directory subtree. // // This function is identical to BuildDirectory.InstallHooks(), // except that it uses the FUSE specific FileAllocator instead // of FilePool. InstallHooks(fileAllocator FileAllocator, errorLogger util.ErrorLogger) // FilterChildren() can be used to traverse over all of the // InitialContentsFetcher and LinkableLeaf objects stored in this // directory hierarchy. For each of the objects, a callback is // provided that can be used to remove the file or the contents // of the directory associated with this object. // // This function can be used by bb_clientd to purge files or // directories that are no longer present in the Content // Addressable Storage at the start of the build. FilterChildren(childFilter ChildFilter) error // Functions inherited from filesystem.Directory. ReadDir() ([]filesystem.FileInfo, error) RemoveAll(name path.Component) error Remove(name path.Component) error }
PrepopulatedDirectory is a Directory that is writable and can contain files of type LinkableLeaf.
By making use of InitialContentsFetcher, it is possible to create subdirectories that are prepopulated with files and directories. These will be instantiated only when accessed. This feature is used by bb_worker to lazily load the input root while a build action is being executed. Similarly, it is used by bb_clientd to lazily instantiate the contents of a Tree object.
func NewInMemoryPrepopulatedDirectory ¶
func NewInMemoryPrepopulatedDirectory(fileAllocator FileAllocator, symlinkFactory SymlinkFactory, errorLogger util.ErrorLogger, handleAllocator StatefulHandleAllocator, initialContentsSorter Sorter, hiddenFilesMatcher StringMatcher, clock clock.Clock) PrepopulatedDirectory
NewInMemoryPrepopulatedDirectory creates a new PrepopulatedDirectory that keeps all directory metadata stored in memory. As the filesystem API does not allow traversing the hierarchy upwards, this directory can be considered the root directory of the hierarchy.
type PrepopulatedDirectoryChild ¶
type PrepopulatedDirectoryChild = Child[PrepopulatedDirectory, LinkableLeaf, Node]
PrepopulatedDirectoryChild is either a PrepopulatedDirectory or a LinkableLeaf, as returned by PrepopulatedDirectory.LookupChild().
type ReadOnlyDirectory ¶
type ReadOnlyDirectory struct{}
ReadOnlyDirectory can be embedded into a Directory to disable all operations that mutate the directory contents.
func (ReadOnlyDirectory) VirtualLink ¶
func (ReadOnlyDirectory) VirtualLink(ctx context.Context, name path.Component, leaf Leaf, requested AttributesMask, out *Attributes) (ChangeInfo, Status)
VirtualLink is an implementation of the link() system call that treats the target directory as being read-only.
func (ReadOnlyDirectory) VirtualMkdir ¶
func (ReadOnlyDirectory) VirtualMkdir(name path.Component, requested AttributesMask, out *Attributes) (Directory, ChangeInfo, Status)
VirtualMkdir is an implementation of the mkdir() system call that treats the target directory as being read-only.
func (ReadOnlyDirectory) VirtualMknod ¶
func (ReadOnlyDirectory) VirtualMknod(ctx context.Context, name path.Component, fileType filesystem.FileType, requested AttributesMask, out *Attributes) (Leaf, ChangeInfo, Status)
VirtualMknod is an implementation of the mknod() system call that treats the target directory as being read-only.
func (ReadOnlyDirectory) VirtualRemove ¶
func (ReadOnlyDirectory) VirtualRemove(name path.Component, removeDirectory, removeLeaf bool) (ChangeInfo, Status)
VirtualRemove is an implementation of the unlink() and rmdir() system calls that treats the target directory as being read-only.
func (ReadOnlyDirectory) VirtualRename ¶
func (ReadOnlyDirectory) VirtualRename(oldName path.Component, newDirectory Directory, newName path.Component) (ChangeInfo, ChangeInfo, Status)
VirtualRename is an implementation of the rename() system call that treats the target directory as being read-only.
func (ReadOnlyDirectory) VirtualSetAttributes ¶
func (ReadOnlyDirectory) VirtualSetAttributes(ctx context.Context, in *Attributes, requested AttributesMask, out *Attributes) Status
VirtualSetAttributes is an implementation of the chmod(), utimensat(), etc. system calls that treats the target directory as being read-only.
func (ReadOnlyDirectory) VirtualSymlink ¶
func (ReadOnlyDirectory) VirtualSymlink(ctx context.Context, pointedTo []byte, linkName path.Component, requested AttributesMask, out *Attributes) (Leaf, ChangeInfo, Status)
VirtualSymlink is an implementation of the symlink() system call that treats the target directory as being read-only.
type ResolvableDigestHandleAllocator ¶
type ResolvableDigestHandleAllocator struct {
// contains filtered or unexported fields
}
ResolvableDigestHandleAllocator is a convenience type for the handle allocator API, used for identifying objects by REv2 digest. It is used by bb_clientd's "cas" directory to give unique file handles to objects stored in the Content Addressable Storage.
Because REv2 objects that include their instance name are too long to fit in NFS file handles, this type uses a stateless allocator for the instance name part. It uses a resolvable allocator only for the object hash and size, as those are generally small enough to fit in the file handle.
This means that every time a new instance name is used, a resolver gets leaked. This is acceptable for most use cases, as the instance names in use tend to be limited.
func NewResolvableDigestHandleAllocator ¶
func NewResolvableDigestHandleAllocator(allocation StatelessHandleAllocation, resolver DigestHandleResolver) *ResolvableDigestHandleAllocator
NewResolvableDigestHandleAllocator creates a new NewResolvableDigestHandleAllocator.
func (*ResolvableDigestHandleAllocator) New ¶
func (a *ResolvableDigestHandleAllocator) New(blobDigest digest.Digest) ResolvableHandleAllocation
New creates a new handle allocation for an object with a given digest.
type ResolvableHandleAllocation ¶
type ResolvableHandleAllocation interface { AsResolvableAllocator(resolver HandleResolver) ResolvableHandleAllocator AsStatelessDirectory(directory Directory) Directory AsLinkableLeaf(leaf LinkableLeaf) LinkableLeaf AsLeaf(leaf Leaf) Leaf }
ResolvableHandleAllocation corresponds to an allocation of a file handle that is not only stateless, but can also be trivially reconstructed based on a small, bounded of information.
TODO: ResolvableHandleAllocators can be nested. The resolver provided to AsResolvableAllocator() is only used for the first level. We could eliminate the argument, but that makes composition harder.
type ResolvableHandleAllocator ¶
type ResolvableHandleAllocator interface {
New(id io.WriterTo) ResolvableHandleAllocation
}
ResolvableHandleAllocator is responsible for allocating file handles that are not only stateless, but can also be trivially reconstructed based on a small, bounded amount of information.
This kind of allocator is generally used by bb_clientd's cas/ subdirectory. This directory allows for the exploration of arbitrary objects stored in the Content Addressable Storage (CAS). This allocator can be used to store the digest of such objects in the file handle, meaning bb_clientd doesn't need to track state for each of the files individually.
The exact amount of space that can be stored in a file handle is protocol specific. NFSv3 and NFSv4 use file handles that are 64 and 128 bytes in size, respectively.
type ShareMask ¶
type ShareMask uint32
ShareMask is a bitmask of operations that are permitted against a Leaf that has been opened.
type Sorter ¶
Sorter is a function type for a sorting algorithm. Its signature is identical to the sort.Sort() function.
This type is used by InMemoryPrepopulatedDirectory to make the policy for sorting the results of VirtualReadDir() configurable. Depending on the use case, it is desirable to use a deterministic algorithm (e.g., alphabetic sorting) or an undeterministic one (e.g., random shuffling).
type StatefulDirectoryHandle ¶
type StatefulDirectoryHandle interface { GetAttributes(requested AttributesMask, attributes *Attributes) NotifyRemoval(name path.Component) Release() }
StatefulDirectoryHandle is a handle that needs to be embedded into stateful directories. It can be used to report mutations to the directory through NotifyRemoval(), or report deletion through Release().
The directory type that embeds the handle must call GetAttributes() as part of Directory.VirtualGetAttributes() to augment the attributes with an inode number and/or file handle.
type StatefulHandleAllocation ¶
type StatefulHandleAllocation interface { StatelessHandleAllocation AsStatefulDirectory(directory Directory) StatefulDirectoryHandle }
StatefulHandleAllocation corresponds to an allocation of a file handle that is unique, meaning it can be used to identify stateful, mutable files or directories.
Exactly one call to one of the methods on this interface needs to be performed to convert the allocation to an actual use of the file handle.
type StatefulHandleAllocator ¶
type StatefulHandleAllocator interface {
New() StatefulHandleAllocation
}
StatefulHandleAllocator is responsible for allocating new file handles, giving files and directories stored in the file system their own identity and lifetime. The exact meaning of identity is implementation specific. In the case of FUSE it can be an inode number/node ID, while in the case of NFSv4 it corresponds to the value of a 128-byte nfs_fh4.
type StatelessHandleAllocation ¶
type StatelessHandleAllocation interface { ResolvableHandleAllocation AsStatelessAllocator() StatelessHandleAllocator }
StatelessHandleAllocation corresponds to an allocation of a file handle that is stateless, meaning it can be used to identify stateless files or directories.
type StatelessHandleAllocator ¶
type StatelessHandleAllocator interface {
New(id io.WriterTo) StatelessHandleAllocation
}
StatelessHandleAllocator is responsible for allocating file handles of files that are stateless, immutable files.
For every handle that is allocated, an identifier needs to be provided in the form of an io.WriterTo. This may be used to give files with the same identifier the same underlying file handle or inode number.
NOTE: Care must be taken that the provided identifier is properly terminated or is prefixed with its own length. Stateless handle allocators may be nested, causing their identifiers to be concatenated. This could cause ambiguity if this rule is not followed.
type Status ¶
type Status int
Status response of operations applied against Node objects.
const ( // StatusOK indicates that the operation succeeded. StatusOK Status = iota // StatusErrAccess indicates that the operation failed due to // permission being denied. StatusErrAccess // StatusErrBadHandle indicates that the provided file handle // failed internal consistency checks. StatusErrBadHandle // StatusErrExist indicates that a file system object of the // specified target name (when creating, renaming or linking) // already exists. StatusErrExist // StatusErrInval indicates that the arguments for this // operation are not valid. StatusErrInval // StatusErrIO indicates that the operation failed due to an I/O // error. StatusErrIO // StatusErrIsDir indicates that a request is made against a // directory when the current operation does not allow a // directory as a target. StatusErrIsDir // StatusErrNoEnt indicate sthat the operation failed due to a // file not existing. StatusErrNoEnt // StatusErrNotDir indicates that a request is made against a // leaf when the current operation does not allow a leaf as a // target. StatusErrNotDir // StatusErrNotEmpty indicates that attempt was made to remove a // directory that was not empty. StatusErrNotEmpty // StatusErrNXIO indicates that a request is made beyond the // limits of the file or device. StatusErrNXIO // StatusErrPerm indicates that the operation was not allowed // because the caller is neither a privileged user (root) nor // the owner of the target of the operation. StatusErrPerm // StatusErrROFS indicates that a modifying operation was // attempted on a read-only file system. StatusErrROFS // StatusErrStale indicates that the file system object referred // to by the file handle no longer exists, or access to it has // been revoked. StatusErrStale // StatusErrSymlink indicates that a request is made against a // symbolic link when the current operation does not allow a // symbolic link as a target. StatusErrSymlink // StatusErrWrongType that a request is made against an object // that is of an invalid type for the current operation, and // there is no more specific error (such as StatusErrIsDir or // StatusErrSymlink) that applies. StatusErrWrongType // StatusErrXDev indicates an attempt to do an operation, such // as linking, that inappropriately crosses a boundary. StatusErrXDev )
type StringMatcher ¶
StringMatcher is a function type that has the same signature as regexp.Regexp's MatchString() method. It is used by InMemoryPrepopulatedDirectory to determine which files should be hidden from directory listings.
type SymlinkFactory ¶
type SymlinkFactory interface {
LookupSymlink(target []byte) LinkableLeaf
}
SymlinkFactory is a factory type for symbolic links. Symbolic links are immutable files; the target to which they point can only be altered by replacing the node entirely (e.g., by first unlinking it from the directory).
var BaseSymlinkFactory SymlinkFactory = symlinkFactory{}
BaseSymlinkFactory can be used to create simple immutable symlink nodes.
func NewHandleAllocatingSymlinkFactory ¶
func NewHandleAllocatingSymlinkFactory(base SymlinkFactory, allocation StatelessHandleAllocation) SymlinkFactory
NewHandleAllocatingSymlinkFactory is a decorator for SymlinkFactory that creates symbolic link nodes that have a stateless handle associated with them.
Because symbolic link contents can be long, it is not possible to use a resolvable allocator here, as that would cause the full contents of the symbolic link to become part of the file handle, which is undesirable. In the case of NFS we want these nodes to be explicitly tracked, using an invisible link count.
type UserSettableSymlink ¶
type UserSettableSymlink struct {
// contains filtered or unexported fields
}
UserSettableSymlink is an implementation of a symbolic link, whose target can be modified using the TemporaryDirectoryInstaller gRPC API.
Instead of just pointing to a single target, this type is capable of storing one target per user. Both when reading and adjusting the symbolic link's target, the public authentication metadata is used to identify the user.
func NewUserSettableSymlink ¶
func NewUserSettableSymlink(buildDirectory *path.Builder) *UserSettableSymlink
NewUserSettableSymlink creates a UserSettableSymlink that doesn't have any targets configured.
func (*UserSettableSymlink) CheckReadiness ¶
func (f *UserSettableSymlink) CheckReadiness(ctx context.Context, request *emptypb.Empty) (*emptypb.Empty, error)
CheckReadiness returns whether the target of the symbolic link is capable of being mutated.
func (*UserSettableSymlink) InstallTemporaryDirectory ¶
func (f *UserSettableSymlink) InstallTemporaryDirectory(ctx context.Context, request *tmp_installer.InstallTemporaryDirectoryRequest) (*emptypb.Empty, error)
InstallTemporaryDirectory sets the target of the symbolic link for the user stored in the authentication metadata.
func (UserSettableSymlink) VirtualAllocate ¶
func (UserSettableSymlink) VirtualApply ¶
func (UserSettableSymlink) VirtualClose ¶
func (UserSettableSymlink) VirtualClose(shareAccess ShareMask)
func (*UserSettableSymlink) VirtualGetAttributes ¶
func (f *UserSettableSymlink) VirtualGetAttributes(ctx context.Context, requested AttributesMask, attributes *Attributes)
VirtualGetAttributes returns the file system attributes of the symbolic link.
func (UserSettableSymlink) VirtualOpenSelf ¶
func (UserSettableSymlink) VirtualOpenSelf(ctx context.Context, shareAccess ShareMask, options *OpenExistingOptions, requested AttributesMask, attributes *Attributes) Status
func (UserSettableSymlink) VirtualRead ¶
func (*UserSettableSymlink) VirtualReadlink ¶
func (f *UserSettableSymlink) VirtualReadlink(ctx context.Context) ([]byte, Status)
VirtualReadlink returns the target of the symbolic link for the calling user.
func (UserSettableSymlink) VirtualSeek ¶
func (UserSettableSymlink) VirtualSeek(offset uint64, regionType filesystem.RegionType) (*uint64, Status)
func (*UserSettableSymlink) VirtualSetAttributes ¶
func (f *UserSettableSymlink) VirtualSetAttributes(ctx context.Context, in *Attributes, requested AttributesMask, out *Attributes) Status
VirtualSetAttributes adjusts the attributes of the symbolic link.
Source Files ¶
- access_monitoring_initial_contents_fetcher.go
- attributes.go
- base_symlink_factory.go
- blob_access_cas_file_factory.go
- byte_range_lock_set.go
- cas_file_factory.go
- cas_initial_contents_fetcher.go
- character_device_factory.go
- child.go
- directory.go
- empty_initial_contents_fetcher.go
- file_allocator.go
- fuse_handle_allocator.go
- handle_allocating_file_allocator.go
- handle_allocating_symlink_factory.go
- handle_allocator.go
- in_memory_prepopulated_directory.go
- initial_contents_fetcher.go
- leaf.go
- linkable_leaf.go
- nfs_handle_allocator.go
- node.go
- permissions.go
- placeholder_file.go
- pool_backed_file_allocator.go
- prepopulated_directory.go
- read_only_directory.go
- resolvable_digest_handle_allocator.go
- resolvable_handle_allocating_cas_file_factory.go
- sorter.go
- special_file.go
- stateless_handle_allocating_cas_file_factory.go
- static_directory.go
- status.go
- symlink_factory.go
- user_settable_symlink.go