Skip to content

Commit

Permalink
Improve FUSE init configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
touilleMan committed Oct 2, 2024
1 parent 5060cff commit b913e09
Showing 1 changed file with 103 additions and 2 deletions.
105 changes: 103 additions & 2 deletions libparsec/crates/platform_mountpoint/src/unix/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::{
ffi::OsStr,
sync::{Arc, Mutex},
time::Duration,
};

use libparsec_client::workspace::{
Expand Down Expand Up @@ -216,8 +217,90 @@ impl fuser::Filesystem for Filesystem {
// see https://libfuse.github.io/doxygen/structfuse__conn__info.html
config: &mut fuser::KernelConfig,
) -> Result<(), libc::c_int> {
// Try to enable readdirplus optimisation, if it's not possible we fallback on regular readdir
let _ = config.add_capabilities(fuser::consts::FUSE_DO_READDIRPLUS);
// See libfuse & Linux documentation for a description of the capabilities.
// See:
// - https://github.com/torvalds/linux/blob/e32cde8d2bd7d251a8f9b434143977ddf13dcec6/include/uapi/linux/fuse.h#L376-L428
// - https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L158

// Here the general idea is to follow libfuse3's default configuration on what
// should be enabled.
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/lib/fuse_lowlevel.c#L2087-L2108

// Note Fuser already set the following capabilities:
// - On Linux: FUSE_ASYNC_READ | FUSE_BIG_WRITES | FUSE_MAX_PAGES
// - On macOS: FUSE_ASYNC_READ | FUSE_CASE_INSENSITIVE | FUSE_VOL_RENAME | FUSE_XTIMES | FUSE_MAX_PAGES

Check warning on line 231 in libparsec/crates/platform_mountpoint/src/unix/filesystem.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (XTIMES)

// `FUSE_POSIX_LOCKS` (remote locking support) is not enabled since we don't
// implement `getlk()` & `setlk()` handlers.
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L179

// `FUSE_FLOCK_LOCKS` is not enabled since we don't implement `flock()` handler.
// Instead we rely on in-kernel POSIX lock emulation.
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L246

// `FUSE_ASYNC_DIO` is not enabled since we don't do direct I/O.
// See:
// - https://www.kernel.org/doc/html/latest/filesystems/fuse-io.html
// - https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L322

// Do not send separate SETATTR request before open(O_TRUNC).
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L188
config
.add_capabilities(fuser::consts::FUSE_ATOMIC_O_TRUNC)
.expect("Capability available");

// Support IOCTL on directories.
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L253
config
.add_capabilities(fuser::consts::FUSE_IOCTL_DIR)
.expect("Capability available");

// Tell FUSE the data may change without going through the filesystem, hence attributes
// validity should be checked on each access (leading to `getattr()` on timeout).
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L275
config
.add_capabilities(fuser::consts::FUSE_AUTO_INVAL_DATA)
.expect("Capability available");

// Enable `readdirplus` support (readdir + lookup in one a single go).
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L283
config
.add_capabilities(fuser::consts::FUSE_DO_READDIRPLUS)
.expect("Capability available");

// Adaptative readdirplus optimization support: still use readdir when lookup is
// has already been done by the previous readdirplus.
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L311
config
.add_capabilities(fuser::consts::FUSE_READDIRPLUS_AUTO)
.expect("Capability available");

// TODO: `FUSE_SPLICE_READ` seems to require `write_buf()` to be implemented, which is
// not even exposed in fuser !
// Allow splice operations (see `man 2 splice`, basically kernal space page-based operations)
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L216
config
.add_capabilities(fuser::consts::FUSE_SPLICE_WRITE)
.expect("Capability available");
config
.add_capabilities(fuser::consts::FUSE_SPLICE_MOVE)
.expect("Capability available");
config
.add_capabilities(fuser::consts::FUSE_SPLICE_READ)
.expect("Capability available");

// Allow parallel lookups and readdir on any given folder (default is serialized).
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L354
config
.add_capabilities(fuser::consts::FUSE_PARALLEL_DIROPS)

Check warning on line 295 in libparsec/crates/platform_mountpoint/src/unix/filesystem.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (DIROPS)
.expect("Capability available");

// Inform the Kernel about the granularity of the timestamps supported by our filesystem.
// See https://github.com/libfuse/libfuse/blob/2aeef499b84b596608181f9b48d589c4f8ffe24a/include/fuse_common.h#L609-L622
config
.set_time_granularity(Duration::from_micros(1))
.expect("Valid granularity");

Ok(())
}

Expand Down Expand Up @@ -1086,6 +1169,17 @@ impl fuser::Filesystem for Filesystem {
offset,
data.len(),
);
let log = std::path::PathBuf::from(format!(
"/home/emmanuel/projects/parsec-cloud/fs_{ino:x}_{offset:x}.log"
));
std::fs::File::options()
.create(true)
.append(true)
.write(true)
.open(log)
.unwrap()
.write_all(data)

Check failure on line 1181 in libparsec/crates/platform_mountpoint/src/unix/filesystem.rs

View workflow job for this annotation

GitHub Actions / rust / 🐧 Linux: 🦀 Rust tests

no method named `write_all` found for struct `std::fs::File` in the current scope
.unwrap();
let reply = reply_on_drop_guard!(reply, fuser::ReplyWrite);
let data = data.to_vec();

Expand All @@ -1096,6 +1190,13 @@ impl fuser::Filesystem for Filesystem {
let offset = u64::try_from(offset).expect("Offset is negative");
match ops.fd_write(fd, offset, &data).await {
Ok(written) => {
log::debug!(
"[FUSE] write DONE (ino: {:#x?}, fh: {}, offset: {}, data.len(): {})",
ino,
fh,
offset,
data.len(),
);
reply.manual().written(written as u32);
}
Err(err) => match err {
Expand Down

0 comments on commit b913e09

Please sign in to comment.