diff options
Diffstat (limited to 'pkg/abi/linux/fuse.go')
-rw-r--r-- | pkg/abi/linux/fuse.go | 710 |
1 files changed, 70 insertions, 640 deletions
diff --git a/pkg/abi/linux/fuse.go b/pkg/abi/linux/fuse.go index c2357a2ee..7e30483ee 100644 --- a/pkg/abi/linux/fuse.go +++ b/pkg/abi/linux/fuse.go @@ -14,20 +14,12 @@ package linux -import ( - "gvisor.dev/gvisor/tools/go_marshal/marshal" - "gvisor.dev/gvisor/tools/go_marshal/primitive" -) - // +marshal type FUSEOpcode uint32 // +marshal type FUSEOpID uint64 -// FUSE_ROOT_ID is the id of root inode. -const FUSE_ROOT_ID = 1 - // Opcodes for FUSE operations. Analogous to the opcodes in include/linux/fuse.h. const ( FUSE_LOOKUP FUSEOpcode = 1 @@ -124,28 +116,61 @@ type FUSEHeaderOut struct { Unique FUSEOpID } +// FUSEWriteIn is the header written by a daemon when it makes a +// write request to the FUSE filesystem. +// +// +marshal +type FUSEWriteIn struct { + // Fh specifies the file handle that is being written to. + Fh uint64 + + // Offset is the offset of the write. + Offset uint64 + + // Size is the size of data being written. + Size uint32 + + // WriteFlags is the flags used during the write. + WriteFlags uint32 + + // LockOwner is the ID of the lock owner. + LockOwner uint64 + + // Flags is the flags for the request. + Flags uint32 + + _ uint32 +} + // FUSE_INIT flags, consistent with the ones in include/uapi/linux/fuse.h. -// Our taget version is 7.23 but we have few implemented in advance. const ( - FUSE_ASYNC_READ = 1 << 0 - FUSE_POSIX_LOCKS = 1 << 1 - FUSE_FILE_OPS = 1 << 2 - FUSE_ATOMIC_O_TRUNC = 1 << 3 - FUSE_EXPORT_SUPPORT = 1 << 4 - FUSE_BIG_WRITES = 1 << 5 - FUSE_DONT_MASK = 1 << 6 - FUSE_SPLICE_WRITE = 1 << 7 - FUSE_SPLICE_MOVE = 1 << 8 - FUSE_SPLICE_READ = 1 << 9 - FUSE_FLOCK_LOCKS = 1 << 10 - FUSE_HAS_IOCTL_DIR = 1 << 11 - FUSE_AUTO_INVAL_DATA = 1 << 12 - FUSE_DO_READDIRPLUS = 1 << 13 - FUSE_READDIRPLUS_AUTO = 1 << 14 - FUSE_ASYNC_DIO = 1 << 15 - FUSE_WRITEBACK_CACHE = 1 << 16 - FUSE_NO_OPEN_SUPPORT = 1 << 17 - FUSE_MAX_PAGES = 1 << 22 // From FUSE 7.28 + FUSE_ASYNC_READ = 1 << 0 + FUSE_POSIX_LOCKS = 1 << 1 + FUSE_FILE_OPS = 1 << 2 + FUSE_ATOMIC_O_TRUNC = 1 << 3 + FUSE_EXPORT_SUPPORT = 1 << 4 + FUSE_BIG_WRITES = 1 << 5 + FUSE_DONT_MASK = 1 << 6 + FUSE_SPLICE_WRITE = 1 << 7 + FUSE_SPLICE_MOVE = 1 << 8 + FUSE_SPLICE_READ = 1 << 9 + FUSE_FLOCK_LOCKS = 1 << 10 + FUSE_HAS_IOCTL_DIR = 1 << 11 + FUSE_AUTO_INVAL_DATA = 1 << 12 + FUSE_DO_READDIRPLUS = 1 << 13 + FUSE_READDIRPLUS_AUTO = 1 << 14 + FUSE_ASYNC_DIO = 1 << 15 + FUSE_WRITEBACK_CACHE = 1 << 16 + FUSE_NO_OPEN_SUPPORT = 1 << 17 + FUSE_PARALLEL_DIROPS = 1 << 18 + FUSE_HANDLE_KILLPRIV = 1 << 19 + FUSE_POSIX_ACL = 1 << 20 + FUSE_ABORT_ERROR = 1 << 21 + FUSE_MAX_PAGES = 1 << 22 + FUSE_CACHE_SYMLINKS = 1 << 23 + FUSE_NO_OPENDIR_SUPPORT = 1 << 24 + FUSE_EXPLICIT_INVAL_DATA = 1 << 25 + FUSE_MAP_ALIGNMENT = 1 << 26 ) // currently supported FUSE protocol version numbers. @@ -154,13 +179,6 @@ const ( FUSE_KERNEL_MINOR_VERSION = 31 ) -// Constants relevant to FUSE operations. -const ( - FUSE_NAME_MAX = 1024 - FUSE_PAGE_SIZE = 4096 - FUSE_DIRENT_ALIGN = 8 -) - // FUSEInitIn is the request sent by the kernel to the daemon, // to negotiate the version and flags. // @@ -181,7 +199,7 @@ type FUSEInitIn struct { } // FUSEInitOut is the reply sent by the daemon to the kernel -// for FUSEInitIn. We target FUSE 7.23; this struct supports 7.28. +// for FUSEInitIn. // // +marshal type FUSEInitOut struct { @@ -222,16 +240,13 @@ type FUSEInitOut struct { // if the value from daemon is too large. MaxPages uint16 - _ uint16 + // MapAlignment is an unknown field and not used by this package at this moment. + // Use as a placeholder to be consistent with the FUSE protocol. + MapAlignment uint16 _ [8]uint32 } -// FUSE_GETATTR_FH is currently the only flag of FUSEGetAttrIn.GetAttrFlags. -// If it is set, the file handle (FUSEGetAttrIn.Fh) is used to indicate the -// object instead of the node id attribute in the request header. -const FUSE_GETATTR_FH = (1 << 0) - // FUSEGetAttrIn is the request sent by the kernel to the daemon, // to get the attribute of a inode. // @@ -252,52 +267,22 @@ type FUSEGetAttrIn struct { // // +marshal type FUSEAttr struct { - // Ino is the inode number of this file. - Ino uint64 - - // Size is the size of this file. - Size uint64 - - // Blocks is the number of the 512B blocks allocated by this file. - Blocks uint64 - - // Atime is the time of last access. - Atime uint64 - - // Mtime is the time of last modification. - Mtime uint64 - - // Ctime is the time of last status change. - Ctime uint64 - - // AtimeNsec is the nano second part of Atime. + Ino uint64 + Size uint64 + Blocks uint64 + Atime uint64 + Mtime uint64 + Ctime uint64 AtimeNsec uint32 - - // MtimeNsec is the nano second part of Mtime. MtimeNsec uint32 - - // CtimeNsec is the nano second part of Ctime. CtimeNsec uint32 - - // Mode contains the file type and mode. - Mode uint32 - - // Nlink is the number of the hard links. - Nlink uint32 - - // UID is user ID of the owner. - UID uint32 - - // GID is group ID of the owner. - GID uint32 - - // Rdev is the device ID if this is a special file. - Rdev uint32 - - // BlkSize is the block size for filesystem I/O. - BlkSize uint32 - - _ uint32 + Mode uint32 + Nlink uint32 + UID uint32 + GID uint32 + Rdev uint32 + BlkSize uint32 + _ uint32 } // FUSEGetAttrOut is the reply sent by the daemon to the kernel @@ -316,558 +301,3 @@ type FUSEGetAttrOut struct { // Attr contains the metadata returned from the FUSE server Attr FUSEAttr } - -// FUSEEntryOut is the reply sent by the daemon to the kernel -// for FUSE_MKNOD, FUSE_MKDIR, FUSE_SYMLINK, FUSE_LINK and -// FUSE_LOOKUP. -// -// +marshal -type FUSEEntryOut struct { - // NodeID is the ID for current inode. - NodeID uint64 - - // Generation is the generation number of inode. - // Used to identify an inode that have different ID at different time. - Generation uint64 - - // EntryValid indicates timeout for an entry. - EntryValid uint64 - - // AttrValid indicates timeout for an entry's attributes. - AttrValid uint64 - - // EntryValidNsec indicates timeout for an entry in nanosecond. - EntryValidNSec uint32 - - // AttrValidNsec indicates timeout for an entry's attributes in nanosecond. - AttrValidNSec uint32 - - // Attr contains the attributes of an entry. - Attr FUSEAttr -} - -// FUSELookupIn is the request sent by the kernel to the daemon -// to look up a file name. -// -// Dynamically-sized objects cannot be marshalled. -type FUSELookupIn struct { - marshal.StubMarshallable - - // Name is a file name to be looked up. - Name string -} - -// MarshalBytes serializes r.name to the dst buffer. -func (r *FUSELookupIn) MarshalBytes(buf []byte) { - copy(buf, r.Name) -} - -// SizeBytes is the size of the memory representation of FUSELookupIn. -// 1 extra byte for null-terminated string. -func (r *FUSELookupIn) SizeBytes() int { - return len(r.Name) + 1 -} - -// MAX_NON_LFS indicates the maximum offset without large file support. -const MAX_NON_LFS = ((1 << 31) - 1) - -// flags returned by OPEN request. -const ( - // FOPEN_DIRECT_IO indicates bypassing page cache for this opened file. - FOPEN_DIRECT_IO = 1 << 0 - // FOPEN_KEEP_CACHE avoids invalidate of data cache on open. - FOPEN_KEEP_CACHE = 1 << 1 - // FOPEN_NONSEEKABLE indicates the file cannot be seeked. - FOPEN_NONSEEKABLE = 1 << 2 -) - -// FUSEOpenIn is the request sent by the kernel to the daemon, -// to negotiate flags and get file handle. -// -// +marshal -type FUSEOpenIn struct { - // Flags of this open request. - Flags uint32 - - _ uint32 -} - -// FUSEOpenOut is the reply sent by the daemon to the kernel -// for FUSEOpenIn. -// -// +marshal -type FUSEOpenOut struct { - // Fh is the file handler for opened file. - Fh uint64 - - // OpenFlag for the opened file. - OpenFlag uint32 - - _ uint32 -} - -// FUSE_READ flags, consistent with the ones in include/uapi/linux/fuse.h. -const ( - FUSE_READ_LOCKOWNER = 1 << 1 -) - -// FUSEReadIn is the request sent by the kernel to the daemon -// for FUSE_READ. -// -// +marshal -type FUSEReadIn struct { - // Fh is the file handle in userspace. - Fh uint64 - - // Offset is the read offset. - Offset uint64 - - // Size is the number of bytes to read. - Size uint32 - - // ReadFlags for this FUSE_READ request. - // Currently only contains FUSE_READ_LOCKOWNER. - ReadFlags uint32 - - // LockOwner is the id of the lock owner if there is one. - LockOwner uint64 - - // Flags for the underlying file. - Flags uint32 - - _ uint32 -} - -// FUSEWriteIn is the first part of the payload of the -// request sent by the kernel to the daemon -// for FUSE_WRITE (struct for FUSE version >= 7.9). -// -// The second part of the payload is the -// binary bytes of the data to be written. -// -// +marshal -type FUSEWriteIn struct { - // Fh is the file handle in userspace. - Fh uint64 - - // Offset is the write offset. - Offset uint64 - - // Size is the number of bytes to write. - Size uint32 - - // ReadFlags for this FUSE_WRITE request. - WriteFlags uint32 - - // LockOwner is the id of the lock owner if there is one. - LockOwner uint64 - - // Flags for the underlying file. - Flags uint32 - - _ uint32 -} - -// FUSEWriteOut is the payload of the reply sent by the daemon to the kernel -// for a FUSE_WRITE request. -// -// +marshal -type FUSEWriteOut struct { - // Size is the number of bytes written. - Size uint32 - - _ uint32 -} - -// FUSEReleaseIn is the request sent by the kernel to the daemon -// when there is no more reference to a file. -// -// +marshal -type FUSEReleaseIn struct { - // Fh is the file handler for the file to be released. - Fh uint64 - - // Flags of the file. - Flags uint32 - - // ReleaseFlags of this release request. - ReleaseFlags uint32 - - // LockOwner is the id of the lock owner if there is one. - LockOwner uint64 -} - -// FUSECreateMeta contains all the static fields of FUSECreateIn, -// which is used for FUSE_CREATE. -// -// +marshal -type FUSECreateMeta struct { - // Flags of the creating file. - Flags uint32 - - // Mode is the mode of the creating file. - Mode uint32 - - // Umask is the current file mode creation mask. - Umask uint32 - _ uint32 -} - -// FUSECreateIn contains all the arguments sent by the kernel to the daemon, to -// atomically create and open a new regular file. -// -// Dynamically-sized objects cannot be marshalled. -type FUSECreateIn struct { - marshal.StubMarshallable - - // CreateMeta contains mode, rdev and umash field for FUSE_MKNODS. - CreateMeta FUSECreateMeta - - // Name is the name of the node to create. - Name string -} - -// MarshalBytes serializes r.CreateMeta and r.Name to the dst buffer. -func (r *FUSECreateIn) MarshalBytes(buf []byte) { - r.CreateMeta.MarshalBytes(buf[:r.CreateMeta.SizeBytes()]) - copy(buf[r.CreateMeta.SizeBytes():], r.Name) -} - -// SizeBytes is the size of the memory representation of FUSECreateIn. -// 1 extra byte for null-terminated string. -func (r *FUSECreateIn) SizeBytes() int { - return r.CreateMeta.SizeBytes() + len(r.Name) + 1 -} - -// FUSEMknodMeta contains all the static fields of FUSEMknodIn, -// which is used for FUSE_MKNOD. -// -// +marshal -type FUSEMknodMeta struct { - // Mode of the inode to create. - Mode uint32 - - // Rdev encodes device major and minor information. - Rdev uint32 - - // Umask is the current file mode creation mask. - Umask uint32 - - _ uint32 -} - -// FUSEMknodIn contains all the arguments sent by the kernel -// to the daemon, to create a new file node. -// -// Dynamically-sized objects cannot be marshalled. -type FUSEMknodIn struct { - marshal.StubMarshallable - - // MknodMeta contains mode, rdev and umash field for FUSE_MKNODS. - MknodMeta FUSEMknodMeta - - // Name is the name of the node to create. - Name string -} - -// MarshalBytes serializes r.MknodMeta and r.Name to the dst buffer. -func (r *FUSEMknodIn) MarshalBytes(buf []byte) { - r.MknodMeta.MarshalBytes(buf[:r.MknodMeta.SizeBytes()]) - copy(buf[r.MknodMeta.SizeBytes():], r.Name) -} - -// SizeBytes is the size of the memory representation of FUSEMknodIn. -// 1 extra byte for null-terminated string. -func (r *FUSEMknodIn) SizeBytes() int { - return r.MknodMeta.SizeBytes() + len(r.Name) + 1 -} - -// FUSESymLinkIn is the request sent by the kernel to the daemon, -// to create a symbolic link. -// -// Dynamically-sized objects cannot be marshalled. -type FUSESymLinkIn struct { - marshal.StubMarshallable - - // Name of symlink to create. - Name string - - // Target of the symlink. - Target string -} - -// MarshalBytes serializes r.Name and r.Target to the dst buffer. -// Left null-termination at end of r.Name and r.Target. -func (r *FUSESymLinkIn) MarshalBytes(buf []byte) { - copy(buf, r.Name) - copy(buf[len(r.Name)+1:], r.Target) -} - -// SizeBytes is the size of the memory representation of FUSESymLinkIn. -// 2 extra bytes for null-terminated string. -func (r *FUSESymLinkIn) SizeBytes() int { - return len(r.Name) + len(r.Target) + 2 -} - -// FUSEEmptyIn is used by operations without request body. -type FUSEEmptyIn struct{ marshal.StubMarshallable } - -// MarshalBytes do nothing for marshal. -func (r *FUSEEmptyIn) MarshalBytes(buf []byte) {} - -// SizeBytes is 0 for empty request. -func (r *FUSEEmptyIn) SizeBytes() int { - return 0 -} - -// FUSEMkdirMeta contains all the static fields of FUSEMkdirIn, -// which is used for FUSE_MKDIR. -// -// +marshal -type FUSEMkdirMeta struct { - // Mode of the directory of create. - Mode uint32 - - // Umask is the user file creation mask. - Umask uint32 -} - -// FUSEMkdirIn contains all the arguments sent by the kernel -// to the daemon, to create a new directory. -// -// Dynamically-sized objects cannot be marshalled. -type FUSEMkdirIn struct { - marshal.StubMarshallable - - // MkdirMeta contains Mode and Umask of the directory to create. - MkdirMeta FUSEMkdirMeta - - // Name of the directory to create. - Name string -} - -// MarshalBytes serializes r.MkdirMeta and r.Name to the dst buffer. -func (r *FUSEMkdirIn) MarshalBytes(buf []byte) { - r.MkdirMeta.MarshalBytes(buf[:r.MkdirMeta.SizeBytes()]) - copy(buf[r.MkdirMeta.SizeBytes():], r.Name) -} - -// SizeBytes is the size of the memory representation of FUSEMkdirIn. -// 1 extra byte for null-terminated Name string. -func (r *FUSEMkdirIn) SizeBytes() int { - return r.MkdirMeta.SizeBytes() + len(r.Name) + 1 -} - -// FUSERmDirIn is the request sent by the kernel to the daemon -// when trying to remove a directory. -// -// Dynamically-sized objects cannot be marshalled. -type FUSERmDirIn struct { - marshal.StubMarshallable - - // Name is a directory name to be removed. - Name string -} - -// MarshalBytes serializes r.name to the dst buffer. -func (r *FUSERmDirIn) MarshalBytes(buf []byte) { - copy(buf, r.Name) -} - -// SizeBytes is the size of the memory representation of FUSERmDirIn. -func (r *FUSERmDirIn) SizeBytes() int { - return len(r.Name) + 1 -} - -// FUSEDirents is a list of Dirents received from the FUSE daemon server. -// It is used for FUSE_READDIR. -// -// Dynamically-sized objects cannot be marshalled. -type FUSEDirents struct { - marshal.StubMarshallable - - Dirents []*FUSEDirent -} - -// FUSEDirent is a Dirent received from the FUSE daemon server. -// It is used for FUSE_READDIR. -// -// Dynamically-sized objects cannot be marshalled. -type FUSEDirent struct { - marshal.StubMarshallable - - // Meta contains all the static fields of FUSEDirent. - Meta FUSEDirentMeta - - // Name is the filename of the dirent. - Name string -} - -// FUSEDirentMeta contains all the static fields of FUSEDirent. -// It is used for FUSE_READDIR. -// -// +marshal -type FUSEDirentMeta struct { - // Inode of the dirent. - Ino uint64 - - // Offset of the dirent. - Off uint64 - - // NameLen is the length of the dirent name. - NameLen uint32 - - // Type of the dirent. - Type uint32 -} - -// SizeBytes is the size of the memory representation of FUSEDirents. -func (r *FUSEDirents) SizeBytes() int { - var sizeBytes int - for _, dirent := range r.Dirents { - sizeBytes += dirent.SizeBytes() - } - - return sizeBytes -} - -// UnmarshalBytes deserializes FUSEDirents from the src buffer. -func (r *FUSEDirents) UnmarshalBytes(src []byte) { - for { - if len(src) <= (*FUSEDirentMeta)(nil).SizeBytes() { - break - } - - // Its unclear how many dirents there are in src. Each dirent is dynamically - // sized and so we can't make assumptions about how many dirents we can allocate. - if r.Dirents == nil { - r.Dirents = make([]*FUSEDirent, 0) - } - - // We have to allocate a struct for each dirent - there must be a better way - // to do this. Linux allocates 1 page to store all the dirents and then - // simply reads them from the page. - var dirent FUSEDirent - dirent.UnmarshalBytes(src) - r.Dirents = append(r.Dirents, &dirent) - - src = src[dirent.SizeBytes():] - } -} - -// SizeBytes is the size of the memory representation of FUSEDirent. -func (r *FUSEDirent) SizeBytes() int { - dataSize := r.Meta.SizeBytes() + len(r.Name) - - // Each Dirent must be padded such that its size is a multiple - // of FUSE_DIRENT_ALIGN. Similar to the fuse dirent alignment - // in linux/fuse.h. - return (dataSize + (FUSE_DIRENT_ALIGN - 1)) & ^(FUSE_DIRENT_ALIGN - 1) -} - -// UnmarshalBytes deserializes FUSEDirent from the src buffer. -func (r *FUSEDirent) UnmarshalBytes(src []byte) { - r.Meta.UnmarshalBytes(src) - src = src[r.Meta.SizeBytes():] - - if r.Meta.NameLen > FUSE_NAME_MAX { - // The name is too long and therefore invalid. We don't - // need to unmarshal the name since it'll be thrown away. - return - } - - buf := make([]byte, r.Meta.NameLen) - name := primitive.ByteSlice(buf) - name.UnmarshalBytes(src[:r.Meta.NameLen]) - r.Name = string(name) -} - -// FATTR_* consts are the attribute flags defined in include/uapi/linux/fuse.h. -// These should be or-ed together for setattr to know what has been changed. -const ( - FATTR_MODE = (1 << 0) - FATTR_UID = (1 << 1) - FATTR_GID = (1 << 2) - FATTR_SIZE = (1 << 3) - FATTR_ATIME = (1 << 4) - FATTR_MTIME = (1 << 5) - FATTR_FH = (1 << 6) - FATTR_ATIME_NOW = (1 << 7) - FATTR_MTIME_NOW = (1 << 8) - FATTR_LOCKOWNER = (1 << 9) - FATTR_CTIME = (1 << 10) -) - -// FUSESetAttrIn is the request sent by the kernel to the daemon, -// to set the attribute(s) of a file. -// -// +marshal -type FUSESetAttrIn struct { - // Valid indicates which attributes are modified by this request. - Valid uint32 - - _ uint32 - - // Fh is used to identify the file if FATTR_FH is set in Valid. - Fh uint64 - - // Size is the size that the request wants to change to. - Size uint64 - - // LockOwner is the owner of the lock that the request wants to change to. - LockOwner uint64 - - // Atime is the access time that the request wants to change to. - Atime uint64 - - // Mtime is the modification time that the request wants to change to. - Mtime uint64 - - // Ctime is the status change time that the request wants to change to. - Ctime uint64 - - // AtimeNsec is the nano second part of Atime. - AtimeNsec uint32 - - // MtimeNsec is the nano second part of Mtime. - MtimeNsec uint32 - - // CtimeNsec is the nano second part of Ctime. - CtimeNsec uint32 - - // Mode is the file mode that the request wants to change to. - Mode uint32 - - _ uint32 - - // UID is the user ID of the owner that the request wants to change to. - UID uint32 - - // GID is the group ID of the owner that the request wants to change to. - GID uint32 - - _ uint32 -} - -// FUSEUnlinkIn is the request sent by the kernel to the daemon -// when trying to unlink a node. -// -// Dynamically-sized objects cannot be marshalled. -type FUSEUnlinkIn struct { - marshal.StubMarshallable - - // Name of the node to unlink. - Name string -} - -// MarshalBytes serializes r.name to the dst buffer, which should -// have size len(r.Name) + 1 and last byte set to 0. -func (r *FUSEUnlinkIn) MarshalBytes(buf []byte) { - copy(buf, r.Name) -} - -// SizeBytes is the size of the memory representation of FUSEUnlinkIn. -// 1 extra byte for null-terminated Name string. -func (r *FUSEUnlinkIn) SizeBytes() int { - return len(r.Name) + 1 -} |