Trait fuse::filesystem::FileSystem
source · pub trait FileSystem {
type Inode: From<u64> + Into<u64>;
type Handle: From<u64> + Into<u64>;
type DirIter: DirectoryIterator;
Show 47 methods
// Provided methods
fn max_buffer_size(&self) -> u32 { ... }
fn init(&self, capable: FsOptions) -> Result<FsOptions> { ... }
fn destroy(&self) { ... }
fn lookup(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr
) -> Result<Entry> { ... }
fn forget(&self, ctx: Context, inode: Self::Inode, count: u64) { ... }
fn batch_forget(&self, ctx: Context, requests: Vec<(Self::Inode, u64)>) { ... }
fn getattr(
&self,
ctx: Context,
inode: Self::Inode,
handle: Option<Self::Handle>
) -> Result<(stat64, Duration)> { ... }
fn setattr(
&self,
ctx: Context,
inode: Self::Inode,
attr: stat64,
handle: Option<Self::Handle>,
valid: SetattrValid
) -> Result<(stat64, Duration)> { ... }
fn readlink(&self, ctx: Context, inode: Self::Inode) -> Result<Vec<u8>> { ... }
fn symlink(
&self,
ctx: Context,
linkname: &CStr,
parent: Self::Inode,
name: &CStr,
security_ctx: Option<&CStr>
) -> Result<Entry> { ... }
fn mknod(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr,
mode: u32,
rdev: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<Entry> { ... }
fn mkdir(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr,
mode: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<Entry> { ... }
fn chromeos_tmpfile(
&self,
ctx: Context,
parent: Self::Inode,
mode: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<Entry> { ... }
fn unlink(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr
) -> Result<()> { ... }
fn rmdir(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr
) -> Result<()> { ... }
fn rename(
&self,
ctx: Context,
olddir: Self::Inode,
oldname: &CStr,
newdir: Self::Inode,
newname: &CStr,
flags: u32
) -> Result<()> { ... }
fn link(
&self,
ctx: Context,
inode: Self::Inode,
newparent: Self::Inode,
newname: &CStr
) -> Result<Entry> { ... }
fn open(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32
) -> Result<(Option<Self::Handle>, OpenOptions)> { ... }
fn create(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr,
mode: u32,
flags: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<(Entry, Option<Self::Handle>, OpenOptions)> { ... }
fn read<W: Write + ZeroCopyWriter>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
w: W,
size: u32,
offset: u64,
lock_owner: Option<u64>,
flags: u32
) -> Result<usize> { ... }
fn write<R: Read + ZeroCopyReader>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
r: R,
size: u32,
offset: u64,
lock_owner: Option<u64>,
delayed_write: bool,
flags: u32
) -> Result<usize> { ... }
fn flush(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
lock_owner: u64
) -> Result<()> { ... }
fn fsync(
&self,
ctx: Context,
inode: Self::Inode,
datasync: bool,
handle: Self::Handle
) -> Result<()> { ... }
fn fallocate(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
mode: u32,
offset: u64,
length: u64
) -> Result<()> { ... }
fn release(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32,
handle: Self::Handle,
flush: bool,
flock_release: bool,
lock_owner: Option<u64>
) -> Result<()> { ... }
fn statfs(&self, ctx: Context, inode: Self::Inode) -> Result<statvfs64> { ... }
fn setxattr(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr,
value: &[u8],
flags: u32
) -> Result<()> { ... }
fn getxattr(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr,
size: u32
) -> Result<GetxattrReply> { ... }
fn listxattr(
&self,
ctx: Context,
inode: Self::Inode,
size: u32
) -> Result<ListxattrReply> { ... }
fn removexattr(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr
) -> Result<()> { ... }
fn opendir(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32
) -> Result<(Option<Self::Handle>, OpenOptions)> { ... }
fn readdir(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
size: u32,
offset: u64
) -> Result<Self::DirIter> { ... }
fn fsyncdir(
&self,
ctx: Context,
inode: Self::Inode,
datasync: bool,
handle: Self::Handle
) -> Result<()> { ... }
fn releasedir(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32,
handle: Self::Handle
) -> Result<()> { ... }
fn access(&self, ctx: Context, inode: Self::Inode, mask: u32) -> Result<()> { ... }
fn ioctl<R: Read>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
flags: IoctlFlags,
cmd: u32,
arg: u64,
in_size: u32,
out_size: u32,
reader: R
) -> Result<IoctlReply> { ... }
fn getlk(&self) -> Result<()> { ... }
fn setlk(&self) -> Result<()> { ... }
fn setlkw(&self) -> Result<()> { ... }
fn bmap(&self) -> Result<()> { ... }
fn poll(&self) -> Result<()> { ... }
fn notify_reply(&self) -> Result<()> { ... }
fn lseek(&self) -> Result<()> { ... }
fn copy_file_range(
&self,
ctx: Context,
inode_src: Self::Inode,
handle_src: Self::Handle,
offset_src: u64,
inode_dst: Self::Inode,
handle_dst: Self::Handle,
offset_dst: u64,
length: u64,
flags: u64
) -> Result<usize> { ... }
fn set_up_mapping<M: Mapper>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
file_offset: u64,
mem_offset: u64,
size: usize,
flags: u32,
mapper: M
) -> Result<()> { ... }
fn remove_mapping<M: Mapper>(
&self,
msgs: &[RemoveMappingOne],
mapper: M
) -> Result<()> { ... }
fn atomic_open(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr,
mode: u32,
flags: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<(Entry, Option<Self::Handle>, OpenOptions)> { ... }
}
Expand description
The main trait that connects a file system with a transport.
Required Associated Types§
sourcetype Inode: From<u64> + Into<u64>
type Inode: From<u64> + Into<u64>
Represents a location in the filesystem tree and can be used to perform operations that act
on the metadata of a file/directory (e.g., getattr
and setattr
). Can also be used as the
starting point for looking up paths in the filesystem tree. An Inode
may support operating
directly on the content of the path that to which it points. FileSystem
implementations
that support this should set the FsOptions::ZERO_MESSAGE_OPEN
option in the return value
of the init
function. On linux based systems, an Inode
is equivalent to opening a file
or directory with the libc::O_PATH
flag.
§Lookup Count
The FileSystem
implementation is required to keep a “lookup count” for every Inode
.
Every time an Entry
is returned by a FileSystem
trait method, this lookup count should
increase by 1. The lookup count for an Inode
decreases when the kernel sends a forget
request. Inode
s with a non-zero lookup count may receive requests from the kernel even
after calls to unlink
, rmdir
or (when overwriting an existing file) rename
.
FileSystem
implementations must handle such requests properly and it is recommended to
defer removal of the Inode
until the lookup count reaches zero. Calls to unlink
, rmdir
or rename
will be followed closely by forget
unless the file or directory is open, in
which case the kernel issues forget
only after the release
or releasedir
calls.
Note that if a file system will be exported over NFS the Inode
’s lifetime must extend even
beyond forget
. See the generation
field in Entry
.
sourcetype Handle: From<u64> + Into<u64>
type Handle: From<u64> + Into<u64>
Represents a file or directory that is open for reading/writing.
sourcetype DirIter: DirectoryIterator
type DirIter: DirectoryIterator
An iterator over the entries of a directory. See the documentation for readdir
for more
details.
Provided Methods§
sourcefn max_buffer_size(&self) -> u32
fn max_buffer_size(&self) -> u32
Maximum size of the buffer that the filesystem can generate data to, including the header. This corresponds to max_write in the initialization.
sourcefn init(&self, capable: FsOptions) -> Result<FsOptions>
fn init(&self, capable: FsOptions) -> Result<FsOptions>
Initialize the file system.
This method is called when a connection to the FUSE kernel module is first established. The
capable
parameter indicates the features that are supported by the kernel module. The
implementation should return the options that it supports. Any options set in the returned
FsOptions
that are not also set in capable
are silently dropped.
sourcefn destroy(&self)
fn destroy(&self)
Clean up the file system.
Called when the filesystem exits. All open Handle
s should be closed and the lookup count
for all open Inode
s implicitly goes to zero. At this point the connection to the FUSE
kernel module may already be gone so implementations should not rely on being able to
communicate with the kernel.
sourcefn lookup(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr
) -> Result<Entry>
fn lookup( &self, ctx: Context, parent: Self::Inode, name: &CStr ) -> Result<Entry>
Look up a directory entry by name and get its attributes.
If this call is successful then the lookup count of the Inode
associated with the returned
Entry
must be increased by 1.
sourcefn forget(&self, ctx: Context, inode: Self::Inode, count: u64)
fn forget(&self, ctx: Context, inode: Self::Inode, count: u64)
Forget about an inode.
Called when the kernel removes an inode from its internal caches. count
indicates the
amount by which the lookup count for the inode should be decreased. If reducing the lookup
count by count
causes it to go to zero, then the implementation may delete the Inode
.
sourcefn batch_forget(&self, ctx: Context, requests: Vec<(Self::Inode, u64)>)
fn batch_forget(&self, ctx: Context, requests: Vec<(Self::Inode, u64)>)
Forget about multiple inodes.
requests
is a vector of (inode, count)
pairs. See the documentation for forget
for
more information.
sourcefn getattr(
&self,
ctx: Context,
inode: Self::Inode,
handle: Option<Self::Handle>
) -> Result<(stat64, Duration)>
fn getattr( &self, ctx: Context, inode: Self::Inode, handle: Option<Self::Handle> ) -> Result<(stat64, Duration)>
Get attributes for a file / directory.
If handle
is not None
, then it contains the handle previously returned by the
implementation after a call to open
or opendir
. However, implementations should still
take care to verify the handle if they do not trust the client (e.g., virtio-fs).
If writeback caching is enabled (FsOptions::WRITEBACK_CACHE
), then the kernel module
likely has a better idea of the length of the file than the file system (for
example, if there was a write that extended the size of the file but has not yet been
flushed). In this case, the st_size
field of the returned struct is ignored.
The returned Duration
indicates how long the returned attributes should be considered
valid by the client. If the attributes are only changed via the FUSE kernel module (i.e.,
the kernel module has exclusive access), then this should be a very large value.
sourcefn setattr(
&self,
ctx: Context,
inode: Self::Inode,
attr: stat64,
handle: Option<Self::Handle>,
valid: SetattrValid
) -> Result<(stat64, Duration)>
fn setattr( &self, ctx: Context, inode: Self::Inode, attr: stat64, handle: Option<Self::Handle>, valid: SetattrValid ) -> Result<(stat64, Duration)>
Set attributes for a file / directory.
If handle
is not None
, then it contains the handle previously returned by the
implementation after a call to open
or opendir
. However, implementations should still
take care to verify the handle if they do not trust the client (e.g., virtio-fs).
The valid
parameter indicates the fields of attr
that may be considered valid and should
be set by the file system. The content of all other fields in attr
is undefined.
If the FsOptions::HANDLE_KILLPRIV
was set during init
, then the implementation is
expected to reset the setuid and setgid bits if the file size or owner is being changed.
This method returns the new attributes after making the modifications requested by the
client. The returned Duration
indicates how long the returned attributes should be
considered valid by the client. If the attributes are only changed via the FUSE kernel
module (i.e., the kernel module has exclusive access), then this should be a very large
value.
sourcefn symlink(
&self,
ctx: Context,
linkname: &CStr,
parent: Self::Inode,
name: &CStr,
security_ctx: Option<&CStr>
) -> Result<Entry>
fn symlink( &self, ctx: Context, linkname: &CStr, parent: Self::Inode, name: &CStr, security_ctx: Option<&CStr> ) -> Result<Entry>
Create a symbolic link.
The file system must create a symbolic link named name
in the directory represented by
parent
, which contains the string linkname
. Returns an Entry
for the newly created
symlink.
If this call is successful then the lookup count of the Inode
associated with the returned
Entry
must be increased by 1.
sourcefn mknod(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr,
mode: u32,
rdev: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<Entry>
fn mknod( &self, ctx: Context, inode: Self::Inode, name: &CStr, mode: u32, rdev: u32, umask: u32, security_ctx: Option<&CStr> ) -> Result<Entry>
Create a file node.
Create a regular file, character device, block device, fifo, or socket node named name
in
the directory represented by inode
. Valid values for mode
and rdev
are the same as
those accepted by the mknod(2)
system call. Returns an Entry
for the newly created node.
When the FsOptions::DONT_MASK
feature is set, the file system is responsible for setting
the permissions of the created node to mode & !umask
.
If this call is successful then the lookup count of the Inode
associated with the returned
Entry
must be increased by 1.
sourcefn mkdir(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr,
mode: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<Entry>
fn mkdir( &self, ctx: Context, parent: Self::Inode, name: &CStr, mode: u32, umask: u32, security_ctx: Option<&CStr> ) -> Result<Entry>
Create a directory.
When the FsOptions::DONT_MASK
feature is set, the file system is responsible for setting
the permissions of the created directory to mode & !umask
. Returns an Entry
for the
newly created directory.
If this call is successful then the lookup count of the Inode
associated with the returned
Entry
must be increased by 1.
sourcefn chromeos_tmpfile(
&self,
ctx: Context,
parent: Self::Inode,
mode: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<Entry>
fn chromeos_tmpfile( &self, ctx: Context, parent: Self::Inode, mode: u32, umask: u32, security_ctx: Option<&CStr> ) -> Result<Entry>
Create an unnamed temporary file.
sourcefn unlink(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> Result<()>
fn unlink(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> Result<()>
Remove a file.
If the file’s inode lookup count is non-zero, then the file system is expected to delay
removal of the inode until the lookup count goes to zero. See the documentation of the
forget
function for more information.
sourcefn rmdir(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> Result<()>
fn rmdir(&self, ctx: Context, parent: Self::Inode, name: &CStr) -> Result<()>
Remove a directory.
If the directory’s inode lookup count is non-zero, then the file system is expected to delay
removal of the inode until the lookup count goes to zero. See the documentation of the
forget
function for more information.
sourcefn rename(
&self,
ctx: Context,
olddir: Self::Inode,
oldname: &CStr,
newdir: Self::Inode,
newname: &CStr,
flags: u32
) -> Result<()>
fn rename( &self, ctx: Context, olddir: Self::Inode, oldname: &CStr, newdir: Self::Inode, newname: &CStr, flags: u32 ) -> Result<()>
Rename a file / directory.
If the destination exists, it should be atomically replaced. If the destination’s inode
lookup count is non-zero, then the file system is expected to delay removal of the inode
until the lookup count goes to zero. See the documentation of the forget
function for more
information.
flags
may be libc::RENAME_EXCHANGE
or libc::RENAME_NOREPLACE
. If
libc::RENAME_NOREPLACE
is specified, the implementation must not overwrite newname
if it
exists and must return an error instead. If libc::RENAME_EXCHANGE
is specified, the
implementation must atomically exchange the two files, i.e., both must exist and neither may
be deleted.
sourcefn link(
&self,
ctx: Context,
inode: Self::Inode,
newparent: Self::Inode,
newname: &CStr
) -> Result<Entry>
fn link( &self, ctx: Context, inode: Self::Inode, newparent: Self::Inode, newname: &CStr ) -> Result<Entry>
Create a hard link.
Create a hard link from inode
to newname
in the directory represented by newparent
.
If this call is successful then the lookup count of the Inode
associated with the returned
Entry
must be increased by 1.
sourcefn open(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32
) -> Result<(Option<Self::Handle>, OpenOptions)>
fn open( &self, ctx: Context, inode: Self::Inode, flags: u32 ) -> Result<(Option<Self::Handle>, OpenOptions)>
Open a file.
Open the file associated with inode
for reading / writing. All values accepted by the
open(2)
system call are valid values for flags
and must be handled by the file system.
However, there are some additional rules:
-
Creation flags (
libc::O_CREAT
,libc::O_EXCL
,libc::O_NOCTTY
) will be filtered out and handled by the kernel. -
The file system should check the access modes (
libc::O_RDONLY
,libc::O_WRONLY
,libc::O_RDWR
) to determine if the operation is permitted. If the file system was mounted with the-o default_permissions
mount option, then this check will also be carried out by the kernel before sending the open request. -
When writeback caching is enabled (
FsOptions::WRITEBACK_CACHE
) the kernel may send read requests even for files opened withlibc::O_WRONLY
. The file system should be prepared to handle this. -
When writeback caching is enabled, the kernel will handle the
libc::O_APPEND
flag. However, this will not work reliably unless the kernel has exclusive access to the file. In this case the file system may either ignore thelibc::O_APPEND
flag or return an error to indicate that reliablelibc::O_APPEND
handling is not available. -
When writeback caching is disabled, the file system is expected to properly handle
libc::O_APPEND
and ensure that each write is appended to the end of the file.
The file system may choose to return a Handle
to refer to the newly opened file. The
kernel will then use this Handle
for all operations on the content of the file (read
,
write
, flush
, release
, fsync
). If the file system does not return a
Handle
then the kernel will use the Inode
for the file to operate on its contents. In
this case the file system may wish to enable the FsOptions::ZERO_MESSAGE_OPEN
feature if
it is supported by the kernel (see below).
The returned OpenOptions
allow the file system to change the way the opened file is
handled by the kernel. See the documentation of OpenOptions
for more information.
If the FsOptions::ZERO_MESSAGE_OPEN
feature is enabled by both the file system
implementation and the kernel, then the file system may return an error of ENOSYS
. This
will be interpreted by the kernel as success and future calls to open
and release
will
be handled by the kernel without being passed on to the file system.
sourcefn create(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr,
mode: u32,
flags: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<(Entry, Option<Self::Handle>, OpenOptions)>
fn create( &self, ctx: Context, parent: Self::Inode, name: &CStr, mode: u32, flags: u32, umask: u32, security_ctx: Option<&CStr> ) -> Result<(Entry, Option<Self::Handle>, OpenOptions)>
Create and open a file.
If the file does not already exist, the file system should create it with the specified
mode
. When the FsOptions::DONT_MASK
feature is set, the file system is responsible for
setting the permissions of the created file to mode & !umask
.
If the file system returns an ENOSYS
error, then the kernel will treat this method as
unimplemented and all future calls to create
will be handled by calling the mknod
and
open
methods instead.
See the documentation for the open
method for more information about opening the file. In
addition to the optional Handle
and the OpenOptions
, the file system must also return an
Entry
for the file. This increases the lookup count for the Inode
associated with the
file by 1.
sourcefn read<W: Write + ZeroCopyWriter>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
w: W,
size: u32,
offset: u64,
lock_owner: Option<u64>,
flags: u32
) -> Result<usize>
fn read<W: Write + ZeroCopyWriter>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, w: W, size: u32, offset: u64, lock_owner: Option<u64>, flags: u32 ) -> Result<usize>
Read data from a file.
Returns size
bytes of data starting from offset off
from the file associated with
inode
or handle
.
flags
contains the flags used to open the file. Similarly, handle
is the Handle
returned by the file system from the open
method, if any. If the file system
implementation did not return a Handle
from open
then the contents of handle
are
undefined.
This method should return exactly the number of bytes requested by the kernel, except in the
case of error or EOF. Otherwise, the kernel will substitute the rest of the data with
zeroes. An exception to this rule is if the file was opened with the “direct I/O” option
(libc::O_DIRECT
), in which case the kernel will forward the return code from this method
to the userspace application that made the system call.
sourcefn write<R: Read + ZeroCopyReader>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
r: R,
size: u32,
offset: u64,
lock_owner: Option<u64>,
delayed_write: bool,
flags: u32
) -> Result<usize>
fn write<R: Read + ZeroCopyReader>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, r: R, size: u32, offset: u64, lock_owner: Option<u64>, delayed_write: bool, flags: u32 ) -> Result<usize>
Write data to a file.
Writes size
bytes of data starting from offset off
to the file associated with inode
or handle
.
flags
contains the flags used to open the file. Similarly, handle
is the Handle
returned by the file system from the open
method, if any. If the file system
implementation did not return a Handle
from open
then the contents of handle
are
undefined.
If the FsOptions::HANDLE_KILLPRIV
feature is not enabled then then the file system is
expected to clear the setuid and setgid bits.
If delayed_write
is true then it indicates that this is a write for buffered data.
This method should return exactly the number of bytes requested by the kernel, except in the
case of error. An exception to this rule is if the file was opened with the “direct I/O”
option (libc::O_DIRECT
), in which case the kernel will forward the return code from this
method to the userspace application that made the system call.
sourcefn flush(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
lock_owner: u64
) -> Result<()>
fn flush( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, lock_owner: u64 ) -> Result<()>
Flush the contents of a file.
This method is called on every close()
of a file descriptor. Since it is possible to
duplicate file descriptors there may be many flush
calls for one call to open
.
File systems should not make any assumptions about when flush
will be
called or even if it will be called at all.
handle
is the Handle
returned by the file system from the open
method, if any. If the
file system did not return a Handle
from open
then the contents of handle
are
undefined.
Unlike fsync
, the file system is not required to flush pending writes. One reason to flush
data is if the file system wants to return write errors during close. However, this is not
portable because POSIX does not require close
to wait for delayed I/O to complete.
If the FsOptions::POSIX_LOCKS
feature is enabled, then the file system must remove all
locks belonging to lock_owner
.
If this method returns an ENOSYS
error then the kernel will treat it as success and all
subsequent calls to flush
will be handled by the kernel without being forwarded to the
file system.
sourcefn fsync(
&self,
ctx: Context,
inode: Self::Inode,
datasync: bool,
handle: Self::Handle
) -> Result<()>
fn fsync( &self, ctx: Context, inode: Self::Inode, datasync: bool, handle: Self::Handle ) -> Result<()>
Synchronize file contents.
File systems must ensure that the file contents have been flushed to disk before returning
from this method. If datasync
is true then only the file data (but not the metadata) needs
to be flushed.
handle
is the Handle
returned by the file system from the open
method, if any. If the
file system did not return a Handle
from open
then the contents of
handle
are undefined.
If this method returns an ENOSYS
error then the kernel will treat it as success and all
subsequent calls to fsync
will be handled by the kernel without being forwarded to the
file system.
sourcefn fallocate(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
mode: u32,
offset: u64,
length: u64
) -> Result<()>
fn fallocate( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, mode: u32, offset: u64, length: u64 ) -> Result<()>
Allocate requested space for file data.
If this function returns success, then the file sytem must guarantee that it is possible to
write up to length
bytes of data starting at offset
without failing due to a lack of
free space on the disk.
handle
is the Handle
returned by the file system from the open
method, if any. If the
file system did not return a Handle
from open
then the contents of handle
are
undefined.
If this method returns an ENOSYS
error then the kernel will treat that as a permanent
failure: all future calls to fallocate
will fail with EOPNOTSUPP
without being forwarded
to the file system.
sourcefn release(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32,
handle: Self::Handle,
flush: bool,
flock_release: bool,
lock_owner: Option<u64>
) -> Result<()>
fn release( &self, ctx: Context, inode: Self::Inode, flags: u32, handle: Self::Handle, flush: bool, flock_release: bool, lock_owner: Option<u64> ) -> Result<()>
Release an open file.
This method is called when there are no more references to an open file: all file descriptors are closed and all memory mappings are unmapped.
For every open
call there will be exactly one release
call (unless the file system is
force-unmounted).
The file system may reply with an error, but error values are not returned to the close()
or munmap()
which triggered the release.
handle
is the Handle
returned by the file system from the open
method, if any. If the
file system did not return a Handle
from open
then the contents of
handle
are undefined.
If flush
is true
then the contents of the file should also be flushed to disk.
sourcefn statfs(&self, ctx: Context, inode: Self::Inode) -> Result<statvfs64>
fn statfs(&self, ctx: Context, inode: Self::Inode) -> Result<statvfs64>
Get information about the file system.
sourcefn setxattr(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr,
value: &[u8],
flags: u32
) -> Result<()>
fn setxattr( &self, ctx: Context, inode: Self::Inode, name: &CStr, value: &[u8], flags: u32 ) -> Result<()>
Set an extended attribute.
If this method fails with an ENOSYS
error, then the kernel will treat that as a permanent
failure. The kernel will return EOPNOTSUPP
for all future calls to setxattr
without
forwarding them to the file system.
Valid values for flags are the same as those accepted by the setxattr(2)
system call and
have the same behavior.
sourcefn getxattr(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr,
size: u32
) -> Result<GetxattrReply>
fn getxattr( &self, ctx: Context, inode: Self::Inode, name: &CStr, size: u32 ) -> Result<GetxattrReply>
Get an extended attribute.
If size
is 0, then the file system should respond with GetxattrReply::Count
and the
number of bytes needed to hold the value. If size
is large enough to hold the value, then
the file system should reply with GetxattrReply::Value
and the value of the extended
attribute. If size
is not 0 but is also not large enough to hold the value, then the file
system should reply with an ERANGE
error.
If this method fails with an ENOSYS
error, then the kernel will treat that as a permanent
failure. The kernel will return EOPNOTSUPP
for all future calls to getxattr
without
forwarding them to the file system.
sourcefn listxattr(
&self,
ctx: Context,
inode: Self::Inode,
size: u32
) -> Result<ListxattrReply>
fn listxattr( &self, ctx: Context, inode: Self::Inode, size: u32 ) -> Result<ListxattrReply>
List extended attribute names.
If size
is 0, then the file system should respond with ListxattrReply::Count
and the
number of bytes needed to hold a \0
byte separated list of the names of all the extended
attributes. If size
is large enough to hold the \0
byte separated list of the attribute
names, then the file system should reply with ListxattrReply::Names
and the list. If
size
is not 0 but is also not large enough to hold the list, then the file system should
reply with an ERANGE
error.
If this method fails with an ENOSYS
error, then the kernel will treat that as a permanent
failure. The kernel will return EOPNOTSUPP
for all future calls to listxattr
without
forwarding them to the file system.
sourcefn removexattr(
&self,
ctx: Context,
inode: Self::Inode,
name: &CStr
) -> Result<()>
fn removexattr( &self, ctx: Context, inode: Self::Inode, name: &CStr ) -> Result<()>
Remove an extended attribute.
If this method fails with an ENOSYS
error, then the kernel will treat that as a permanent
failure. The kernel will return EOPNOTSUPP
for all future calls to removexattr
without
forwarding them to the file system.
sourcefn opendir(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32
) -> Result<(Option<Self::Handle>, OpenOptions)>
fn opendir( &self, ctx: Context, inode: Self::Inode, flags: u32 ) -> Result<(Option<Self::Handle>, OpenOptions)>
Open a directory for reading.
The file system may choose to return a Handle
to refer to the newly opened directory. The
kernel will then use this Handle
for all operations on the content of the directory
(readdir
, readdirplus
, fsyncdir
, releasedir
). If the file system does not return a
Handle
then the kernel will use the Inode
for the directory to operate on its contents.
In this case the file system may wish to enable the FsOptions::ZERO_MESSAGE_OPENDIR
feature if it is supported by the kernel (see below).
The returned OpenOptions
allow the file system to change the way the opened directory is
handled by the kernel. See the documentation of OpenOptions
for more information.
If the FsOptions::ZERO_MESSAGE_OPENDIR
feature is enabled by both the file system
implementation and the kernel, then the file system may return an error of ENOSYS
. This
will be interpreted by the kernel as success and future calls to opendir
and releasedir
will be handled by the kernel without being passed on to the file system.
sourcefn readdir(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
size: u32,
offset: u64
) -> Result<Self::DirIter>
fn readdir( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, size: u32, offset: u64 ) -> Result<Self::DirIter>
Read a directory.
handle
is the Handle
returned by the file system from the opendir
method, if any. If
the file system did not return a Handle
from opendir
then the contents of handle
are
undefined.
size
indicates the maximum number of bytes that should be returned by this method.
If offset
is non-zero then it corresponds to one of the offset
values from a DirEntry
that was previously returned by a call to readdir
for the same handle. In this case the
file system should skip over the entries before the position defined by the offset
value.
If entries were added or removed while the Handle
is open then the file system may still
include removed entries or skip newly created entries. However, adding or removing entries
should never cause the file system to skip over unrelated entries or include an entry more
than once. This means that offset
cannot be a simple index and must include sufficient
information to uniquely determine the next entry in the list even when the set of entries is
being changed.
The file system may return entries for the current directory (“.”) and parent directory (“..”) but is not required to do so. If the file system does not return these entries, then they are implicitly added by the kernel.
The lookup count for Inode
s associated with the returned directory entries is NOT
affected by this method.
sourcefn fsyncdir(
&self,
ctx: Context,
inode: Self::Inode,
datasync: bool,
handle: Self::Handle
) -> Result<()>
fn fsyncdir( &self, ctx: Context, inode: Self::Inode, datasync: bool, handle: Self::Handle ) -> Result<()>
Synchronize the contents of a directory.
File systems must ensure that the directory contents have been flushed to disk before
returning from this method. If datasync
is true then only the directory data (but not the
metadata) needs to be flushed.
handle
is the Handle
returned by the file system from the opendir
method, if any. If
the file system did not return a Handle
from opendir
then the contents of
handle
are undefined.
If this method returns an ENOSYS
error then the kernel will treat it as success and all
subsequent calls to fsyncdir
will be handled by the kernel without being forwarded to the
file system.
sourcefn releasedir(
&self,
ctx: Context,
inode: Self::Inode,
flags: u32,
handle: Self::Handle
) -> Result<()>
fn releasedir( &self, ctx: Context, inode: Self::Inode, flags: u32, handle: Self::Handle ) -> Result<()>
Release an open directory.
For every opendir
call there will be exactly one releasedir
call (unless the file system
is force-unmounted).
handle
is the Handle
returned by the file system from the opendir
method, if any. If
the file system did not return a Handle
from opendir
then the contents of handle
are
undefined.
flags
contains used the flags used to open the directory in opendir
.
sourcefn access(&self, ctx: Context, inode: Self::Inode, mask: u32) -> Result<()>
fn access(&self, ctx: Context, inode: Self::Inode, mask: u32) -> Result<()>
Check file access permissions.
This method is called when a userspace process in the client makes an access()
or
chdir()
system call. If the file system was mounted with the -o default_permissions
mount option, then the kernel will perform these checks itself and this method will not be
called.
If this method returns an ENOSYS
error, then the kernel will treat it as a permanent
success: all future calls to access
will return success without being forwarded to the
file system.
sourcefn ioctl<R: Read>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
flags: IoctlFlags,
cmd: u32,
arg: u64,
in_size: u32,
out_size: u32,
reader: R
) -> Result<IoctlReply>
fn ioctl<R: Read>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, flags: IoctlFlags, cmd: u32, arg: u64, in_size: u32, out_size: u32, reader: R ) -> Result<IoctlReply>
Perform an ioctl on a file or directory.
handle
is the Handle
returned by the file system from the open
or opendir
methods,
if any. If the file system did not return a Handle
from then the contents of handle
are
undefined.
If flags
contains IoctlFlags::UNRESTRICTED
then the file system may retry the ioctl
after informing the kernel about the input and output areas. If flags
does not contain
IoctlFlags::UNRESTRICTED
then the kernel will prepare the input and output areas according
to the encoding in the ioctl command. In that case the ioctl cannot be retried.
cmd
is the ioctl request made by the calling process, truncated to 32 bits.
arg
is the argument provided by the calling process.
in_size
is the length of the additional data that accompanies the request. The file system
may fetch this data from reader
.
out_size
is the length of the output area prepared by the kernel to hold the response to
the ioctl.
sourcefn notify_reply(&self) -> Result<()>
fn notify_reply(&self) -> Result<()>
TODO: support this
sourcefn copy_file_range(
&self,
ctx: Context,
inode_src: Self::Inode,
handle_src: Self::Handle,
offset_src: u64,
inode_dst: Self::Inode,
handle_dst: Self::Handle,
offset_dst: u64,
length: u64,
flags: u64
) -> Result<usize>
fn copy_file_range( &self, ctx: Context, inode_src: Self::Inode, handle_src: Self::Handle, offset_src: u64, inode_dst: Self::Inode, handle_dst: Self::Handle, offset_dst: u64, length: u64, flags: u64 ) -> Result<usize>
Copy a range of data from one file to another
Performs an optimized copy between two file descriptors without the additional cost of transferring data through the kernel module to user space (glibc) and then back into the file system again.
In case this method is not implemented, glibc falls back to reading data from the source and writing to the destination.
If this method fails with an ENOSYS
error, then the kernel will treat that as a permanent
failure. The kernel will return EOPNOTSUPP
for all future calls to copy_file_range
without forwarding them to the file system.
All values accepted by the copy_file_range(2)
system call are valid values for flags
and
must be handled by the file system.
sourcefn set_up_mapping<M: Mapper>(
&self,
ctx: Context,
inode: Self::Inode,
handle: Self::Handle,
file_offset: u64,
mem_offset: u64,
size: usize,
flags: u32,
mapper: M
) -> Result<()>
fn set_up_mapping<M: Mapper>( &self, ctx: Context, inode: Self::Inode, handle: Self::Handle, file_offset: u64, mem_offset: u64, size: usize, flags: u32, mapper: M ) -> Result<()>
Set up memory mappings.
Used to set up file mappings in DAX window.
§Arguments
file_offset
- Offset into the file to start the mapping.mem_offset
- Offset in Memory Window.size
- Length of mapping required.flags
- Bit field ofFUSE_SETUPMAPPING_FLAGS_*
.mapper
- Mapper object which performs the mapping.
sourcefn remove_mapping<M: Mapper>(
&self,
msgs: &[RemoveMappingOne],
mapper: M
) -> Result<()>
fn remove_mapping<M: Mapper>( &self, msgs: &[RemoveMappingOne], mapper: M ) -> Result<()>
Remove memory mappings.
Used to tear down file mappings in DAX window. This method must be supported when
set_up_mapping
is supported.
sourcefn atomic_open(
&self,
ctx: Context,
parent: Self::Inode,
name: &CStr,
mode: u32,
flags: u32,
umask: u32,
security_ctx: Option<&CStr>
) -> Result<(Entry, Option<Self::Handle>, OpenOptions)>
fn atomic_open( &self, ctx: Context, parent: Self::Inode, name: &CStr, mode: u32, flags: u32, umask: u32, security_ctx: Option<&CStr> ) -> Result<(Entry, Option<Self::Handle>, OpenOptions)>
Lookup and open/create the file
In this call, program first do a lookup on the file. Then depending upon flags combination, either do create + open, open only or return error. In all successful cases, it will return the dentry. For return value’s handle and open options atomic_open should apply same rules to handle flags and configuration in open/create system call.
This function is called when the client supports FUSE_OPEN_ATOMIC. Implementing atomic_open is optional. When the it’s not implemented, the client fall back to send lookup and open requests separately.
§Specification
If file was indeed newly created (as a result of O_CREAT), then set
FOPEN_FILE_CREATED
bit in struct OpenOptions open
. This bit is used by
crosvm to inform the fuse client to set FILE_CREATED
bit in `struct
fuse_file_info’.
All flags applied to open/create should be handled samely in atomic open, only the following are exceptions:
- The O_NOCTTY is filtered out by fuse client.
- O_TRUNC is filtered out by VFS for O_CREAT, O_EXCL combination.
§Implementation
To implement this API, you need to handle the following cases:
a) File does not exist
- O_CREAT:
- Create file with specified mode
- Set
FOPEN_FILE_CREATED
bit instruct OpenOptions open
- Open the file
- Return d_entry and file handler
- ~O_CREAT:
- ENOENT
b) File exist already (exception is O_EXCL)
- O_CREAT:
- Open the file
- Return d_entry and file handler
- O_EXCL:
- EEXIST
c) File is symbol link
- Return dentry and file handler