Skip to content

Commit 48edd73

Browse files
author
Henry Huang
committed
passthroughfs: support splice for fusedev
add a smoke testcase for splice Signed-off-by: Henry Huang <henry.hj@antgroup.com>
1 parent 3507c57 commit 48edd73

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

src/passthrough/sync_io.rs

+30
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,21 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
656656

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

659+
#[cfg(all(target_os = "linux", feature = "fusedev"))]
660+
match w.append_fd_buf(&f.as_raw_fd(), size as usize, Some(offset)) {
661+
Ok(len) => {
662+
return Ok(len);
663+
}
664+
Err(e) => {
665+
let err_code = e.raw_os_error().unwrap_or(-1);
666+
if err_code != libc::ENOSYS && err_code != libc::ENOTSUP && err_code != libc::EINVAL
667+
{
668+
return Err(e);
669+
}
670+
// fallback to write_from
671+
}
672+
}
673+
659674
w.write_from(&mut *f, size as usize, offset)
660675
}
661676

@@ -696,6 +711,21 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
696711
None
697712
};
698713

714+
#[cfg(all(target_os = "linux", feature = "fusedev"))]
715+
match r.splice_to(&f.as_raw_fd(), size as usize, Some(offset)) {
716+
Ok(len) => {
717+
return Ok(len);
718+
}
719+
Err(e) => {
720+
let err_code = e.raw_os_error().unwrap_or(-1);
721+
if err_code != libc::ENOSYS && err_code != libc::ENOTSUP && err_code != libc::EINVAL
722+
{
723+
return Err(e);
724+
}
725+
// fallback to read_to
726+
}
727+
}
728+
699729
r.read_to(&mut *f, size as usize, offset)
700730
}
701731

tests/example/passthroughfs.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ pub struct Daemon {
1919
server: Arc<Server<Arc<Vfs>>>,
2020
thread_cnt: u32,
2121
session: Option<FuseSession>,
22+
enable_splice: bool,
2223
}
2324

2425
#[allow(dead_code)]
2526
impl Daemon {
2627
/// Creates a fusedev daemon instance
27-
pub fn new(src: &str, mountpoint: &str, thread_cnt: u32) -> Result<Self> {
28+
pub fn new(src: &str, mountpoint: &str, thread_cnt: u32, enable_splice: bool) -> Result<Self> {
2829
// create vfs
2930
let vfs = Vfs::new(VfsOptions {
3031
no_open: false,
@@ -47,6 +48,7 @@ impl Daemon {
4748
server: Arc::new(Server::new(Arc::new(vfs))),
4849
thread_cnt,
4950
session: None,
51+
enable_splice,
5052
})
5153
}
5254

@@ -60,6 +62,7 @@ impl Daemon {
6062
let mut server = FuseServer {
6163
server: self.server.clone(),
6264
ch: se.new_channel().unwrap(),
65+
enable_splice: self.enable_splice,
6366
};
6467
let _thread = thread::Builder::new()
6568
.name("fuse_server".to_string())
@@ -93,12 +96,21 @@ impl Drop for Daemon {
9396
struct FuseServer {
9497
server: Arc<Server<Arc<Vfs>>>,
9598
ch: FuseChannel,
99+
enable_splice: bool,
96100
}
97101

98102
impl FuseServer {
99103
fn svc_loop(&mut self) -> Result<()> {
100104
// Given error EBADF, it means kernel has shut down this session.
101105
let _ebadf = std::io::Error::from_raw_os_error(libc::EBADF);
106+
if self.enable_splice {
107+
if self.server.is_support_splice_write() {
108+
self.ch.enable_splice_write().unwrap();
109+
}
110+
if self.server.is_support_splice_read() {
111+
self.ch.enable_splice_read().unwrap();
112+
}
113+
}
102114
loop {
103115
if let Some((reader, writer)) = self
104116
.ch

tests/smoke.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,19 @@ mod fusedev_tests {
8888
let tmp_dir = TempDir::new().unwrap();
8989
let mnt_dir = tmp_dir.as_path().to_str().unwrap();
9090
info!(
91-
"test passthroughfs src {:?} mountpoint {}",
91+
"test passthroughfs src {:?} mountpoint {} splice false",
9292
src_dir, mnt_dir
9393
);
9494

95-
let mut daemon = passthroughfs::Daemon::new(src_dir, mnt_dir, 2).unwrap();
95+
let mut daemon = passthroughfs::Daemon::new(src_dir, mnt_dir, 2, false).unwrap();
96+
daemon.mount().unwrap();
97+
std::thread::sleep(std::time::Duration::from_secs(1));
98+
assert!(validate_two_git_directory(src_dir, mnt_dir));
99+
daemon.umount().unwrap();
100+
drop(daemon);
101+
// test with splice
102+
std::thread::sleep(std::time::Duration::from_secs(1));
103+
let mut daemon = passthroughfs::Daemon::new(src_dir, mnt_dir, 2, true).unwrap();
96104
daemon.mount().unwrap();
97105
std::thread::sleep(std::time::Duration::from_secs(1));
98106
assert!(validate_two_git_directory(src_dir, mnt_dir));

0 commit comments

Comments
 (0)