Skip to content

Commit

Permalink
passthroughfs: support splice for fusedev
Browse files Browse the repository at this point in the history
add a smoke testcase for splice

Signed-off-by: Henry Huang <henry.hj@antgroup.com>
  • Loading branch information
Henry Huang committed Jan 22, 2024
1 parent 3507c57 commit 8646133
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
30 changes: 30 additions & 0 deletions src/passthrough/sync_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,21 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {

let mut f = ManuallyDrop::new(f);

#[cfg(all(target_os = "linux", feature = "fusedev"))]
match w.append_fd_buf(&f.as_raw_fd(), size as usize, Some(offset)) {
Ok(len) => {
return Ok(len);
}
Err(e) => {
let err_code = e.raw_os_error().unwrap_or(-1);
if err_code != libc::ENOSYS && err_code != libc::ENOTSUP && err_code != libc::EINVAL
{
return Err(e);
}
// fallback to write_from
}
}

w.write_from(&mut *f, size as usize, offset)
}

Expand Down Expand Up @@ -696,6 +711,21 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
None
};

#[cfg(all(target_os = "linux", feature = "fusedev"))]
match r.splice_to(&f.as_raw_fd(), size as usize, Some(offset)) {
Ok(len) => {
return Ok(len);
}
Err(e) => {
let err_code = e.raw_os_error().unwrap_or(-1);
if err_code != libc::ENOSYS && err_code != libc::ENOTSUP && err_code != libc::EINVAL
{
return Err(e);
}
// fallback to read_to
}
}

r.read_to(&mut *f, size as usize, offset)
}

Expand Down
14 changes: 13 additions & 1 deletion tests/example/passthroughfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ pub struct Daemon {
server: Arc<Server<Arc<Vfs>>>,
thread_cnt: u32,
session: Option<FuseSession>,
enable_splice: bool,
}

#[allow(dead_code)]
impl Daemon {
/// Creates a fusedev daemon instance
pub fn new(src: &str, mountpoint: &str, thread_cnt: u32) -> Result<Self> {
pub fn new(src: &str, mountpoint: &str, thread_cnt: u32, enable_splice: bool) -> Result<Self> {
// create vfs
let vfs = Vfs::new(VfsOptions {
no_open: false,
Expand All @@ -47,6 +48,7 @@ impl Daemon {
server: Arc::new(Server::new(Arc::new(vfs))),
thread_cnt,
session: None,
enable_splice,
})
}

Expand All @@ -60,6 +62,7 @@ impl Daemon {
let mut server = FuseServer {
server: self.server.clone(),
ch: se.new_channel().unwrap(),
enable_splice: self.enable_splice,
};
let _thread = thread::Builder::new()
.name("fuse_server".to_string())
Expand Down Expand Up @@ -93,12 +96,21 @@ impl Drop for Daemon {
struct FuseServer {
server: Arc<Server<Arc<Vfs>>>,
ch: FuseChannel,
enable_splice: bool,
}

impl FuseServer {
fn svc_loop(&mut self) -> Result<()> {
// Given error EBADF, it means kernel has shut down this session.
let _ebadf = std::io::Error::from_raw_os_error(libc::EBADF);
if self.enable_splice {
if self.server.is_support_splice_write() {
self.ch.enable_splice_write().unwrap();
}
if self.server.is_support_splice_read() {
self.ch.enable_splice_read().unwrap();
}
}
loop {
if let Some((reader, writer)) = self
.ch
Expand Down
25 changes: 23 additions & 2 deletions tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,32 @@ mod fusedev_tests {
let tmp_dir = TempDir::new().unwrap();
let mnt_dir = tmp_dir.as_path().to_str().unwrap();
info!(
"test passthroughfs src {:?} mountpoint {}",
"test passthroughfs src {:?} mountpoint {} splice false",
src_dir, mnt_dir
);

let mut daemon = passthroughfs::Daemon::new(src_dir, mnt_dir, 2).unwrap();
let mut daemon = passthroughfs::Daemon::new(src_dir, mnt_dir, 2, false).unwrap();
daemon.mount().unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
assert!(validate_two_git_directory(src_dir, mnt_dir));
daemon.umount().unwrap();
Ok(())
}

#[test]
#[ignore] // it depends on privileged mode to pass through /dev/fuse
fn integration_test_tree_gitrepo_with_splice() -> Result<()> {
// test the fuse-rs repository
let src = Path::new(".").canonicalize().unwrap();
let src_dir = src.to_str().unwrap();
let tmp_dir = TempDir::new().unwrap();
let mnt_dir = tmp_dir.as_path().to_str().unwrap();
info!(
"test passthroughfs src {:?} mountpoint {} splice true",
src_dir, mnt_dir
);

let mut daemon = passthroughfs::Daemon::new(src_dir, mnt_dir, 2, true).unwrap();
daemon.mount().unwrap();
std::thread::sleep(std::time::Duration::from_secs(1));
assert!(validate_two_git_directory(src_dir, mnt_dir));
Expand Down

0 comments on commit 8646133

Please sign in to comment.