-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Run xfstests on pathrough fs. Signed-off-by: Wei Zhang <[email protected]>
- Loading branch information
1 parent
4064d1b
commit 6cc253d
Showing
6 changed files
with
308 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: Rust | ||
|
||
on: | ||
push: | ||
branches: '*' | ||
pull_request: | ||
branches: [ master ] | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
RUST_BACKTRACE: 1 | ||
|
||
jobs: | ||
xfstests_on_passthrough: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Install Rust | ||
uses: actions-rs/toolchain@v1 | ||
with: | ||
profile: minimal | ||
toolchain: stable | ||
override: true | ||
- name: Build passthrough binary | ||
run: | | ||
cd tests/passthrough | ||
cargo build --release | ||
sudo install -t /usr/sbin/ -m 700 ./target/release/passthrough | ||
- name: Setup and run xfstest | ||
run: | | ||
cd $GITHUB_WORKSPACE | ||
sudo ./tests/scripts/xfstests_pathr.sh | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
/target | ||
**/target | ||
**/*.rs.bk | ||
**/Cargo.lock | ||
**/.vscode | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "passthrough" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
fuse-backend-rs = { path = "../../", features = ["fusedev"] } | ||
log = ">=0.4.6" | ||
libc = ">=0.2.68" | ||
simple_logger = ">=1.13.0" | ||
signal-hook = ">=0.3.10" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
use log::{error, info, warn, LevelFilter}; | ||
use std::env; | ||
use std::fs; | ||
use std::io::{Error, Result}; | ||
use std::path::Path; | ||
use std::sync::Arc; | ||
use std::thread; | ||
|
||
use signal_hook::{consts::TERM_SIGNALS, iterator::Signals}; | ||
|
||
use fuse_backend_rs::api::{server::Server, Vfs, VfsOptions}; | ||
use fuse_backend_rs::passthrough::{Config, PassthroughFs}; | ||
use fuse_backend_rs::transport::{FuseChannel, FuseSession}; | ||
|
||
use simple_logger::SimpleLogger; | ||
|
||
/// A fusedev daemon example | ||
#[allow(dead_code)] | ||
pub struct Daemon { | ||
mountpoint: String, | ||
server: Arc<Server<Arc<Vfs>>>, | ||
thread_cnt: u32, | ||
session: Option<FuseSession>, | ||
} | ||
|
||
#[allow(dead_code)] | ||
impl Daemon { | ||
/// Creates a fusedev daemon instance | ||
pub fn new(src: &str, mountpoint: &str, thread_cnt: u32) -> Result<Self> { | ||
// create vfs | ||
let vfs = Vfs::new(VfsOptions { | ||
no_open: false, | ||
no_opendir: false, | ||
..Default::default() | ||
}); | ||
|
||
// create passthrough fs | ||
let mut cfg = Config::default(); | ||
cfg.root_dir = src.to_string(); | ||
cfg.do_import = false; | ||
let fs = PassthroughFs::<()>::new(cfg).unwrap(); | ||
fs.import().unwrap(); | ||
|
||
// attach passthrough fs to vfs root | ||
vfs.mount(Box::new(fs), "/").unwrap(); | ||
|
||
Ok(Daemon { | ||
mountpoint: mountpoint.to_string(), | ||
server: Arc::new(Server::new(Arc::new(vfs))), | ||
thread_cnt, | ||
session: None, | ||
}) | ||
} | ||
|
||
/// Mounts a fusedev daemon to the mountpoint, then start service threads to handle | ||
/// FUSE requests. | ||
pub fn mount(&mut self) -> Result<()> { | ||
let mut se = | ||
FuseSession::new(Path::new(&self.mountpoint), "testpassthrough", "", false).unwrap(); | ||
se.mount().unwrap(); | ||
for _ in 0..self.thread_cnt { | ||
let mut server = FuseServer { | ||
server: self.server.clone(), | ||
ch: se.new_channel().unwrap(), | ||
}; | ||
let _thread = thread::Builder::new() | ||
.name("fuse_server".to_string()) | ||
.spawn(move || { | ||
info!("new fuse thread"); | ||
let _ = server.svc_loop(); | ||
warn!("fuse service thread exits"); | ||
}) | ||
.unwrap(); | ||
} | ||
self.session = Some(se); | ||
Ok(()) | ||
} | ||
|
||
/// Umounts and destroies a fusedev daemon | ||
pub fn umount(&mut self) -> Result<()> { | ||
if let Some(mut se) = self.session.take() { | ||
se.umount().unwrap(); | ||
se.wake().unwrap(); | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
impl Drop for Daemon { | ||
fn drop(&mut self) { | ||
let _ = self.umount(); | ||
} | ||
} | ||
|
||
struct FuseServer { | ||
server: Arc<Server<Arc<Vfs>>>, | ||
ch: FuseChannel, | ||
} | ||
|
||
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); | ||
loop { | ||
if let Some((reader, writer)) = self | ||
.ch | ||
.get_request() | ||
.map_err(|_| std::io::Error::from_raw_os_error(libc::EINVAL))? | ||
{ | ||
if let Err(e) = self | ||
.server | ||
.handle_message(reader, writer.into(), None, None) | ||
{ | ||
match e { | ||
fuse_backend_rs::Error::EncodeMessage(_ebadf) => { | ||
break; | ||
} | ||
_ => { | ||
error!("Handling fuse message failed"); | ||
continue; | ||
} | ||
} | ||
} | ||
} else { | ||
info!("fuse server exits"); | ||
break; | ||
} | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
struct Args { | ||
src: String, | ||
dest: String, | ||
} | ||
|
||
fn help() { | ||
println!("Usage:\n passthrough <src> <dest>\n"); | ||
} | ||
|
||
fn parse_args() -> Result<Args> { | ||
let args = env::args().collect::<Vec<String>>(); | ||
let cmd_args = Args { | ||
src: args[1].clone(), | ||
dest: args[2].clone(), | ||
}; | ||
if cmd_args.src.len() == 0 || cmd_args.dest.len() == 0 { | ||
help(); | ||
return Err(Error::from_raw_os_error(libc::EINVAL)); | ||
} | ||
Ok(cmd_args) | ||
} | ||
|
||
fn main() -> Result<()> { | ||
SimpleLogger::new() | ||
.with_level(LevelFilter::Info) | ||
.init() | ||
.unwrap(); | ||
let args = parse_args().unwrap(); | ||
|
||
// Check if src exists, create dir if not. | ||
let src = Path::new(args.src.as_str()); | ||
let src_dir = src.to_str().unwrap(); | ||
if src.exists() { | ||
if !src.is_dir() { | ||
error!("src {} is not a directory", src_dir); | ||
return Err(Error::from_raw_os_error(libc::EINVAL)); | ||
} | ||
} else { | ||
fs::create_dir_all(src_dir).unwrap(); | ||
} | ||
|
||
let dest = Path::new(args.dest.as_str()); | ||
let dest_dir = dest.to_str().unwrap(); | ||
if dest.exists() { | ||
if !dest.is_dir() { | ||
error!("dest {} is not a directory", dest_dir); | ||
return Err(Error::from_raw_os_error(libc::EINVAL)); | ||
} | ||
} else { | ||
fs::create_dir_all(dest_dir).unwrap(); | ||
} | ||
info!( | ||
"test passthroughfs src {:?} mountpoint {}", | ||
src_dir, dest_dir | ||
); | ||
|
||
let mut daemon = Daemon::new(src_dir, dest_dir, 2).unwrap(); | ||
daemon.mount().unwrap(); | ||
|
||
// main thread | ||
let mut signals = Signals::new(TERM_SIGNALS).unwrap(); | ||
for _sig in signals.forever() { | ||
break; | ||
} | ||
|
||
daemon.umount().unwrap(); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Exclude list for tests that we know are broken in passthrough fs | ||
# | ||
generic/002 | ||
generic/184 | ||
generic/426 | ||
generic/434 | ||
generic/467 | ||
generic/471 | ||
generic/477 | ||
generic/591 | ||
generic/633 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#!/bin/bash | ||
|
||
current_dir=$(dirname $(realpath $0)) | ||
|
||
sudo apt-get update | ||
sudo apt-get install acl attr automake bc dbench dump e2fsprogs fio gawk \ | ||
gcc git indent libacl1-dev libaio-dev libcap-dev libgdbm-dev libtool \ | ||
libtool-bin liburing-dev libuuid1 lvm2 make psmisc python3 quota sed \ | ||
uuid-dev uuid-runtime xfsprogs linux-headers-$(uname -r) sqlite3 \ | ||
exfatprogs f2fs-tools ocfs2-tools udftools xfsdump \ | ||
xfslibs-dev | ||
|
||
# clone xfstests and install. | ||
cd /tmp/ | ||
git clone git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git | ||
cd xfstests-dev | ||
make | ||
sudo make install | ||
# overwrite local config. | ||
cat >local.config <<EOF | ||
export TEST_DEV=testpassthrough | ||
export TEST_DIR=/tmp/pathr_dst | ||
export FSTYP=fuse | ||
export FUSE_SUBTYP=.testpassthrough | ||
EOF | ||
|
||
# create fuse overlay mount script. | ||
# /tmp/testoverlay must exists. | ||
sudo cat >/usr/sbin/mount.fuse.testpassthrough <<EOF | ||
#!/bin/bash | ||
ulimit -n 1048576 | ||
exec /usr/sbin/passthrough /tmp/pathr_src /tmp/pathr_dst \ | ||
1>>/tmp/testpassthrough.log 2>&1 & | ||
sleep 1 | ||
EOF | ||
sudo chmod +x /usr/sbin/mount.fuse.testpassthrough | ||
|
||
# create related dirs. | ||
mkdir -p /tmp/pathr_src /tmp/pathr_dst | ||
|
||
echo "====> Start to run xfstests." | ||
# run tests. | ||
cd /tmp/xfstests-dev | ||
# Some tests are not supported by fuse or cannot pass currently. | ||
sudo ./check -fuse -E $current_dir/xfstests_pathr.exclude | ||
|
||
|