block: sparse: Add unit tests for write_zeroes and punch_hole fallback

Exercise the EOPNOTSUPP fallback path using memfd, which shares
the same backing as tmpfs and triggers the fallback without
requiring privileges or a specific filesystem.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-07-17 16:13:40 +02:00
committed by Rob Bradford
parent 028c99b39c
commit 9474c07526

View File

@@ -105,3 +105,55 @@ pub(crate) fn write_zeroes(
Ok(())
}
#[cfg(test)]
mod tests {
use std::ffi::CString;
use std::fs::File;
use std::os::unix::fs::FileExt;
use std::os::unix::io::FromRawFd;
use super::*;
// Create a memfd backed file. memfd uses the same backing as tmpfs,
// so fallocate with ZERO_RANGE and PUNCH_HOLE returns EOPNOTSUPP,
// exercising the fallback path.
fn memfd_file() -> AlignedFile {
let name = CString::new("ch_sparse_test").unwrap();
// SAFETY: memfd_create is a safe syscall that returns a new fd.
let fd = unsafe { libc::memfd_create(name.as_ptr(), 0) };
assert!(fd >= 0, "memfd_create failed");
// SAFETY: fd is a valid open file descriptor we just created.
let f = unsafe { File::from_raw_fd(fd) };
AlignedFile::new(f, false)
}
#[test]
fn write_zeroes_fallback() {
let mut f = memfd_file();
f.file().write_all_at(&vec![0xAA; 4096], 0).unwrap();
write_zeroes(&mut f, false, 512, 1024).unwrap();
let mut buf = vec![0xFFu8; 4096];
f.file().read_exact_at(&mut buf, 0).unwrap();
assert!(buf[..512].iter().all(|&b| b == 0xAA));
assert!(buf[512..1536].iter().all(|&b| b == 0));
assert!(buf[1536..].iter().all(|&b| b == 0xAA));
}
#[test]
fn punch_hole_fallback() {
let mut f = memfd_file();
f.file().write_all_at(&vec![0xBB; 4096], 0).unwrap();
punch_hole(&mut f, false, 1024, 2048).unwrap();
let mut buf = vec![0xFFu8; 4096];
f.file().read_exact_at(&mut buf, 0).unwrap();
assert!(buf[..1024].iter().all(|&b| b == 0xBB));
assert!(buf[1024..3072].iter().all(|&b| b == 0));
assert!(buf[3072..].iter().all(|&b| b == 0xBB));
}
}