use std::os::unix::fs::MetadataExt;
use crate::passthrough::PassthroughFs;
pub trait DaxFsExt {
fn open_inode_for_dax(&self, inode: u64, writable: bool) -> std::io::Result<std::fs::File>;
}
impl DaxFsExt for PassthroughFs {
fn open_inode_for_dax(&self, inode: u64, writable: bool) -> std::io::Result<std::fs::File> {
let registered_ino = self.kernel_ino_for(inode).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("inode {inode} not found in passthrough table"),
)
})?;
let path = self
.inode_path(inode)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::NotFound, e.to_string()))?;
let file = std::fs::OpenOptions::new()
.read(true)
.write(writable)
.open(&path)?;
let fd_ino = file.metadata()?.ino();
if fd_ino != registered_ino {
tracing::warn!(
inode,
path = %path.display(),
fd_ino,
registered_ino,
"TOCTOU mismatch: inode was swapped after registration; rejecting DAX mapping"
);
return Err(std::io::Error::from_raw_os_error(libc::EIO));
}
Ok(file)
}
}