use super::{InodeLocation, InodeMigrationInfo};
use crate::passthrough::file_handle::{self, FileOrHandle, SerializableFileHandle};
use crate::passthrough::inode_store::{InodeData, StrongInodeReference};
use crate::passthrough::PassthroughFs;
use crate::util::ResultErrorContext;
use std::fmt::{self, Display};
use std::io;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
pub(in crate::passthrough) struct FileHandle {
pub handle: SerializableFileHandle,
}
pub(in crate::passthrough::device_state) struct Constructor<'a> {
fs: &'a PassthroughFs,
cancel: Arc<AtomicBool>,
}
impl<'a> Constructor<'a> {
pub fn new(fs: &'a PassthroughFs, cancel: Arc<AtomicBool>) -> Self {
Constructor { fs, cancel }
}
pub fn execute(self) {
for inode_data in self.fs.inodes.iter() {
if self.cancel.load(Ordering::Relaxed) {
break;
}
if inode_data.migration_info.lock().unwrap().is_some() {
continue;
}
if let Err(err) = self.set_migration_info(&inode_data) {
error!(
"Inode {} ({}): {err}",
inode_data.inode,
inode_data.identify(&self.fs.proc_self_fd),
);
}
}
}
}
impl FileHandle {
pub fn new(handle: SerializableFileHandle) -> Self {
FileHandle { handle }
}
pub(super) fn for_each_strong_reference<F: FnMut(StrongInodeReference)>(self, _f: F) {}
}
impl From<FileHandle> for InodeLocation {
fn from(fh: FileHandle) -> Self {
InodeLocation::FileHandle(fh)
}
}
impl Display for FileHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[file handle: {}]", self.handle)
}
}
impl Constructor<'_> {
fn set_migration_info(&self, inode_data: &InodeData) -> io::Result<()> {
let handle: SerializableFileHandle = match &inode_data.file_or_handle {
FileOrHandle::File(file) => file_handle::FileHandle::from_fd_fail_hard(file)
.err_context(|| "Failed to generate file handle")?
.into(),
FileOrHandle::Handle(handle) => handle.inner().into(),
FileOrHandle::Invalid(err) => return Err(io::Error::new(
err.kind(),
format!("Inode is invalid because of an error during the preceding migration, which was: {err}"),
)),
};
let mig_info = InodeMigrationInfo::new_internal(
&self.fs.cfg,
FileHandle::new(handle.clone()),
|| Ok(handle),
)?;
*inode_data.migration_info.lock().unwrap() = Some(mig_info);
Ok(())
}
}