look up inodes by path
also DirEntry::name now no longer returns option invalid chars get replaced by ?
This commit is contained in:
parent
7f6c304709
commit
19340bd4ee
6 changed files with 291 additions and 44 deletions
|
|
@ -2,9 +2,11 @@ mod fuse;
|
|||
mod inode;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use fat_bits::dir::DirEntry;
|
||||
use fat_bits::{FatFs, SliceLike};
|
||||
use fxhash::FxHashMap;
|
||||
use log::debug;
|
||||
|
||||
use crate::inode::Inode;
|
||||
|
|
@ -23,6 +25,7 @@ pub struct FatFuse {
|
|||
|
||||
ino_by_first_cluster: BTreeMap<u32, u64>,
|
||||
ino_by_fh: BTreeMap<u64, u64>,
|
||||
ino_by_path: FxHashMap<Rc<str>, u64>,
|
||||
}
|
||||
|
||||
impl Drop for FatFuse {
|
||||
|
|
@ -35,9 +38,16 @@ impl Drop for FatFuse {
|
|||
}
|
||||
|
||||
println!("ino_by_fh: {}", self.ino_by_fh.len());
|
||||
|
||||
println!("ino_by_path: {}", self.ino_by_path.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// SAFETY
|
||||
///
|
||||
/// do NOT leak Rc<str> from this type
|
||||
unsafe impl Send for FatFuse {}
|
||||
|
||||
impl FatFuse {
|
||||
pub fn new<S>(data: S) -> anyhow::Result<FatFuse>
|
||||
where
|
||||
|
|
@ -57,6 +67,7 @@ impl FatFuse {
|
|||
inode_table: BTreeMap::new(),
|
||||
ino_by_first_cluster: BTreeMap::new(),
|
||||
ino_by_fh: BTreeMap::new(),
|
||||
ino_by_path: FxHashMap::default(),
|
||||
};
|
||||
|
||||
// TODO: build and insert root dir inode
|
||||
|
|
@ -126,6 +137,10 @@ impl FatFuse {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(old_ino) = self.ino_by_path.insert(new_inode.path(), ino) {
|
||||
debug!("ejected old {} -> {} path to ino mapping", new_inode.path(), old_ino);
|
||||
}
|
||||
|
||||
new_inode
|
||||
}
|
||||
|
||||
|
|
@ -157,13 +172,45 @@ impl FatFuse {
|
|||
} else {
|
||||
// does not match removed inode, leave it as is
|
||||
debug!(
|
||||
"removed inode with ino {} from table, but it's first cluster pointer to ino {} instead",
|
||||
"removed inode with ino {} from table, but its first cluster pointed to ino {} instead",
|
||||
ino, found_ino
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let entry = self.ino_by_path.entry(inode.path());
|
||||
|
||||
match entry {
|
||||
std::collections::hash_map::Entry::Vacant(_) => debug!(
|
||||
"removed inode with ino {} from table, but it's path did not point to any ino",
|
||||
ino
|
||||
),
|
||||
std::collections::hash_map::Entry::Occupied(occupied_entry) => {
|
||||
let found_ino = *occupied_entry.get();
|
||||
|
||||
if found_ino == ino {
|
||||
// matches our inode, remove it
|
||||
occupied_entry.remove();
|
||||
} else {
|
||||
// does not match removed inode, leave it as is
|
||||
debug!(
|
||||
"removed inode with ino {} from table, but its path pointed to ino {} instead",
|
||||
ino, found_ino
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(parent_inode) = self.get_inode_mut(inode.parent_ino()) else {
|
||||
panic!("parent inode {} does not exists anymore", inode.parent_ino());
|
||||
};
|
||||
|
||||
// dec refcount
|
||||
parent_inode.dec_ref_count(1);
|
||||
}
|
||||
|
||||
fn get_inode(&self, ino: u64) -> Option<&Inode> {
|
||||
|
|
@ -174,20 +221,51 @@ impl FatFuse {
|
|||
self.inode_table.get_mut(&ino)
|
||||
}
|
||||
|
||||
fn get_or_make_inode_by_dir_entry(&mut self, dir_entry: &DirEntry) -> &mut Inode {
|
||||
if self
|
||||
.get_inode_by_first_cluster_mut(dir_entry.first_cluster())
|
||||
.is_some()
|
||||
fn get_or_make_inode_by_dir_entry(
|
||||
&mut self,
|
||||
dir_entry: &DirEntry,
|
||||
parent_ino: u64,
|
||||
parent_path: Rc<str>,
|
||||
) -> &mut Inode {
|
||||
if dir_entry.first_cluster() != 0
|
||||
&& self
|
||||
.get_inode_by_first_cluster_mut(dir_entry.first_cluster())
|
||||
.is_some()
|
||||
{
|
||||
return self
|
||||
.get_inode_by_first_cluster_mut(dir_entry.first_cluster())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let path = {
|
||||
let mut path = parent_path.as_ref().to_owned();
|
||||
|
||||
if parent_ino != inode::ROOT_INO {
|
||||
// root inode already has trailing slash
|
||||
path.push('/');
|
||||
}
|
||||
|
||||
path += &dir_entry.name_string();
|
||||
|
||||
path
|
||||
};
|
||||
|
||||
if self.get_inode_by_path_mut(&path).is_some() {
|
||||
return self.get_inode_by_path_mut(&path).unwrap();
|
||||
}
|
||||
|
||||
// no inode found, make a new one
|
||||
let ino = self.next_ino();
|
||||
|
||||
let inode = Inode::new(&self.fat_fs, dir_entry, ino, self.uid, self.gid);
|
||||
let Some(parent_inode) = self.get_inode_mut(parent_ino) else {
|
||||
// TODO: what do we do here? should not happen
|
||||
panic!("parent_ino {} does not lead to inode", parent_ino);
|
||||
};
|
||||
|
||||
// inc ref of parent
|
||||
parent_inode.inc_ref_count();
|
||||
|
||||
let inode = Inode::new(&self.fat_fs, dir_entry, ino, self.uid, self.gid, path, parent_ino);
|
||||
|
||||
self.insert_inode(inode)
|
||||
}
|
||||
|
|
@ -235,9 +313,9 @@ impl FatFuse {
|
|||
}
|
||||
|
||||
pub fn get_inode_by_fh(&self, fh: u64) -> Option<&Inode> {
|
||||
let ino = self.ino_by_fh.get(&fh)?;
|
||||
let ino = *self.ino_by_fh.get(&fh)?;
|
||||
|
||||
if let Some(inode) = self.inode_table.get(ino) {
|
||||
if let Some(inode) = self.get_inode(ino) {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!("fh {} is mapped to ino {}, but inode is not in table", fh, ino);
|
||||
|
|
@ -247,9 +325,9 @@ impl FatFuse {
|
|||
}
|
||||
|
||||
pub fn get_inode_by_fh_mut(&mut self, fh: u64) -> Option<&mut Inode> {
|
||||
let ino = self.ino_by_fh.get(&fh)?;
|
||||
let ino = *self.ino_by_fh.get(&fh)?;
|
||||
|
||||
if let Some(inode) = self.inode_table.get_mut(ino) {
|
||||
if let Some(inode) = self.get_inode_mut(ino) {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!("fh {} is mapped to ino {}, but inode is not in table", fh, ino);
|
||||
|
|
@ -257,4 +335,28 @@ impl FatFuse {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inode_by_path(&self, path: &str) -> Option<&Inode> {
|
||||
let ino = *self.ino_by_path.get(path)?;
|
||||
|
||||
if let Some(inode) = self.get_inode(ino) {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!("path {} is mapped to ino {}, but inode is not in table", path, ino);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inode_by_path_mut(&mut self, path: &str) -> Option<&mut Inode> {
|
||||
let ino = *self.ino_by_path.get(path)?;
|
||||
|
||||
if let Some(inode) = self.get_inode_mut(ino) {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!("path {} is mapped to ino {}, but inode is not in table", path, ino);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue