use crate::common::{
BackingFile, LoopbackDevice, Mount, single_mount, write_test_data,
};
use btrfs_uapi::{
filesystem::sync,
scrub::{scrub_cancel, scrub_start},
};
use nix::errno::Errno;
use std::{fs::File, os::unix::io::AsFd};
#[test]
#[ignore = "requires elevated privileges"]
fn scrub_healthy() {
let (_td, mnt) = single_mount();
write_test_data(mnt.path(), "data.bin", 10_000_000);
sync(mnt.fd()).unwrap();
let progress = scrub_start(mnt.fd(), 1, false).expect("scrub_start failed");
assert!(
progress.data_bytes_scrubbed > 0,
"should have scrubbed some data bytes: {progress:?}",
);
assert!(
progress.is_clean(),
"healthy filesystem should have zero errors: {progress:?}"
);
}
#[test]
#[ignore = "requires elevated privileges"]
fn scrub_readonly() {
let (_td, mnt) = single_mount();
write_test_data(mnt.path(), "data.bin", 10_000_000);
sync(mnt.fd()).unwrap();
let progress =
scrub_start(mnt.fd(), 1, true).expect("scrub_start readonly failed");
assert!(
progress.data_bytes_scrubbed > 0,
"readonly scrub should still scrub data: {progress:?}",
);
assert!(
progress.is_clean(),
"readonly scrub should have zero errors: {progress:?}"
);
crate::common::verify_test_data(mnt.path(), "data.bin", 10_000_000);
}
#[test]
#[ignore = "requires elevated privileges"]
fn scrub_cancel_test() {
let td = tempfile::tempdir().unwrap();
let f = BackingFile::new(td.path(), "disk.img", 512_000_000);
f.mkfs();
let lo = LoopbackDevice::new(f);
let mnt = Mount::new(lo, td.path());
write_test_data(mnt.path(), "data.bin", 200_000_000);
sync(mnt.fd()).unwrap();
let mount_path = mnt.path().to_path_buf();
let scrub_thread = std::thread::spawn(move || {
let file =
File::open(&mount_path).expect("open mount in thread failed");
scrub_start(file.as_fd(), 1, false)
});
std::thread::sleep(std::time::Duration::from_millis(100));
match scrub_cancel(mnt.fd()) {
Ok(()) => {}
Err(Errno::ENOTCONN) => {}
Err(e) => panic!("unexpected error from scrub_cancel: {e}"),
}
let result = scrub_thread.join().expect("scrub thread panicked");
match result {
Ok(progress) => {
assert!(
progress.bytes_scrubbed() > 0,
"should have scrubbed something"
);
}
Err(Errno::ECANCELED) => { }
Err(e) => panic!("scrub returned unexpected error: {e}"),
}
}