enter the Rc-RefCell madness
This commit is contained in:
parent
2b01b9ff0e
commit
ea3e2a76c4
12 changed files with 619 additions and 353 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use std::ffi::c_int;
|
||||
use std::io::Read;
|
||||
use std::io::{Read, Write};
|
||||
use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ use fuser::{FileType, Filesystem};
|
|||
use libc::{EBADF, EINVAL, EIO, EISDIR, ENOENT, ENOSYS, ENOTDIR};
|
||||
use log::{debug, error};
|
||||
|
||||
use crate::{FatFuse, Inode};
|
||||
use crate::FatFuse;
|
||||
|
||||
const TTL: Duration = Duration::from_secs(1);
|
||||
|
||||
|
|
@ -50,56 +50,34 @@ impl Filesystem for FatFuse {
|
|||
|
||||
debug!("looking up file {} with parent ino {}", name, parent);
|
||||
|
||||
let Some(parent_inode) = self.get_inode(parent) else {
|
||||
let Some(parent_inode) = self.get_inode(parent).cloned() else {
|
||||
// parent inode does not exist
|
||||
// TODO: how can we make sure this does not happed?
|
||||
// TODO: panic?
|
||||
debug!("could not find inode for parent ino {}", parent);
|
||||
reply.error(EIO);
|
||||
|
||||
reply.error(ENOENT);
|
||||
return;
|
||||
};
|
||||
|
||||
// let Ok(mut dir_iter) = parent_inode.dir_iter(&self.fat_fs) else {
|
||||
// reply.error(ENOTDIR);
|
||||
// return;
|
||||
// };
|
||||
let parent_inode = parent_inode.borrow();
|
||||
|
||||
// let Some(dir_entry) =
|
||||
// dir_iter.find(|dir_entry| dir_entry.name_string().as_deref() == Some(name))
|
||||
// else {
|
||||
// reply.error(ENOENT);
|
||||
// return;
|
||||
// };
|
||||
let dir_entry: DirEntry =
|
||||
match parent_inode
|
||||
.dir_iter(&self.fat_fs)
|
||||
.and_then(|mut dir_iter| {
|
||||
dir_iter
|
||||
.find(|dir_entry| &dir_entry.name_string() == name)
|
||||
.ok_or(ENOENT)
|
||||
}) {
|
||||
Ok(dir_entry) => dir_entry,
|
||||
Err(err) => {
|
||||
debug!("error: {}", err);
|
||||
reply.error(err);
|
||||
|
||||
let dir_entry: DirEntry = match parent_inode
|
||||
.dir_iter(&self.fat_fs)
|
||||
// .map_err(|_| ENOTDIR)
|
||||
.and_then(|mut dir_iter| {
|
||||
dir_iter
|
||||
.find(|dir_entry| &dir_entry.name_string() == name)
|
||||
.ok_or(ENOENT)
|
||||
}) {
|
||||
Ok(dir_entry) => dir_entry,
|
||||
Err(err) => {
|
||||
debug!("error: {}", err);
|
||||
reply.error(err);
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// let inode = match self.get_inode_by_first_cluster(dir_entry.first_cluster()) {
|
||||
// Some(inode) => inode,
|
||||
// None => {
|
||||
// // 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);
|
||||
|
||||
// self.insert_inode(inode)
|
||||
// }
|
||||
// };
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let inode = self.get_or_make_inode_by_dir_entry(
|
||||
&dir_entry,
|
||||
|
|
@ -107,6 +85,8 @@ impl Filesystem for FatFuse {
|
|||
parent_inode.path(),
|
||||
);
|
||||
|
||||
let mut inode = inode.borrow_mut();
|
||||
|
||||
let attr = inode.file_attr();
|
||||
let generation = inode.generation();
|
||||
|
||||
|
|
@ -118,19 +98,21 @@ impl Filesystem for FatFuse {
|
|||
fn forget(&mut self, _req: &fuser::Request<'_>, ino: u64, nlookup: u64) {
|
||||
debug!("forgetting ino {} ({} times)", ino, nlookup);
|
||||
|
||||
let Some(inode) = self.get_inode_mut(ino) else {
|
||||
let Some(inode) = self.get_inode(ino).cloned() else {
|
||||
debug!("tried to forget {} refs of inode {}, but was not found", ino, nlookup);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
// *ref_count = ref_count.saturating_sub(nlookup);
|
||||
let mut inode_ref = inode.borrow_mut();
|
||||
|
||||
if inode.dec_ref_count(nlookup) == 0 {
|
||||
debug!("dropping inode with ino {}", inode.ino());
|
||||
if inode_ref.dec_ref_count(nlookup) == 0 {
|
||||
debug!("dropping inode {}", inode_ref.ino());
|
||||
|
||||
drop(inode_ref);
|
||||
|
||||
// no more references, drop inode
|
||||
self.drop_inode(ino);
|
||||
self.drop_inode(inode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,20 +128,20 @@ impl Filesystem for FatFuse {
|
|||
|
||||
let inode = if let Some(fh) = fh {
|
||||
let Some(inode) = self.get_inode_by_fh(fh) else {
|
||||
reply.error(EIO);
|
||||
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
};
|
||||
|
||||
inode
|
||||
} else if let Some(inode) = self.get_inode(ino) {
|
||||
} else if let Some(inode) = self.get_inode(ino).cloned() {
|
||||
inode
|
||||
} else {
|
||||
reply.error(EIO);
|
||||
|
||||
reply.error(ENOENT);
|
||||
return;
|
||||
};
|
||||
|
||||
let inode = inode.borrow();
|
||||
|
||||
let attr = inode.file_attr();
|
||||
|
||||
reply.attr(&TTL, &attr);
|
||||
|
|
@ -189,6 +171,17 @@ impl Filesystem for FatFuse {
|
|||
ino, mode, uid, gid, size, fh, flags
|
||||
);
|
||||
reply.error(ENOSYS);
|
||||
return;
|
||||
|
||||
// TODO: implement this properly
|
||||
// let Some(inode) = self.get_inode(ino) else {
|
||||
// debug!("tried to get inode {ino}, but not found");
|
||||
//
|
||||
// reply.error(ENOENT);
|
||||
// return;
|
||||
// };
|
||||
//
|
||||
// reply.attr(&TTL, &inode.file_attr());
|
||||
}
|
||||
|
||||
fn readlink(&mut self, _req: &fuser::Request<'_>, ino: u64, reply: fuser::ReplyData) {
|
||||
|
|
@ -272,7 +265,7 @@ impl Filesystem for FatFuse {
|
|||
|
||||
fn open(&mut self, _req: &fuser::Request<'_>, ino: u64, _flags: i32, reply: fuser::ReplyOpen) {
|
||||
if !self.inode_table.contains_key(&ino) {
|
||||
reply.error(EINVAL);
|
||||
reply.error(ENOENT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -321,10 +314,12 @@ impl Filesystem for FatFuse {
|
|||
return;
|
||||
};
|
||||
|
||||
let inode = inode.borrow();
|
||||
|
||||
if inode.ino() != ino {
|
||||
debug!("fh {fh} is associated with inode {} instead of {ino}", inode.ino());
|
||||
|
||||
reply.error(EIO);
|
||||
reply.error(EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -361,6 +356,8 @@ impl Filesystem for FatFuse {
|
|||
}
|
||||
};
|
||||
|
||||
debug!("read {n} bytes");
|
||||
|
||||
reply.data(&buf[..n]);
|
||||
}
|
||||
|
||||
|
|
@ -371,23 +368,102 @@ impl Filesystem for FatFuse {
|
|||
fh: u64,
|
||||
offset: i64,
|
||||
data: &[u8],
|
||||
write_flags: u32,
|
||||
flags: i32,
|
||||
lock_owner: Option<u64>,
|
||||
_write_flags: u32,
|
||||
_flags: i32,
|
||||
_lock_owner: Option<u64>,
|
||||
reply: fuser::ReplyWrite,
|
||||
) {
|
||||
debug!(
|
||||
"[Not Implemented] write(ino: {:#x?}, fh: {}, offset: {}, data.len(): {}, \
|
||||
write_flags: {:#x?}, flags: {:#x?}, lock_owner: {:?})",
|
||||
ino,
|
||||
fh,
|
||||
offset,
|
||||
data.len(),
|
||||
write_flags,
|
||||
flags,
|
||||
lock_owner
|
||||
);
|
||||
reply.error(ENOSYS);
|
||||
debug!("new write request: ino={ino} fh={fh} offset={offset} data={data:?}");
|
||||
|
||||
if offset < 0 {
|
||||
debug!("tried to write with negative offset {offset}");
|
||||
|
||||
reply.error(EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
let offset = offset as u64;
|
||||
|
||||
let Some(inode) = self.get_inode_by_fh(fh) else {
|
||||
debug!("no inode associated with fh {fh} (given ino: {ino}");
|
||||
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
};
|
||||
|
||||
let inode = inode.borrow();
|
||||
|
||||
if inode.is_read_only() {
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
}
|
||||
|
||||
if inode.ino() != ino {
|
||||
debug!("fh {fh} points to ino {}, but ino {ino} was given", inode.ino());
|
||||
|
||||
reply.error(EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if !inode.is_file() {
|
||||
debug!("tried to use read on directory {ino}");
|
||||
|
||||
reply.error(EISDIR);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut writer = match inode.file_writer(&self.fat_fs) {
|
||||
Ok(writer) => writer,
|
||||
Err(err) => {
|
||||
reply.error(err);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// if writer.skip(offset) != offset {
|
||||
// // writer is at EOF, bail
|
||||
|
||||
// }
|
||||
|
||||
let cur_offset = writer.skip(offset);
|
||||
|
||||
// can't seek more than we requested
|
||||
assert!(cur_offset <= offset);
|
||||
|
||||
let mut bytes_written = 0;
|
||||
|
||||
if cur_offset < offset {
|
||||
// tried to set offset beyond EOF
|
||||
// fill with zeros
|
||||
let zeros = vec![0; (offset - cur_offset) as usize];
|
||||
|
||||
debug!("writing {} zeros", zeros.len());
|
||||
|
||||
if let Err(err) = writer.write_all(&zeros) {
|
||||
debug!("writing zeros returned error: {err}");
|
||||
|
||||
reply.error(EIO);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written += zeros.len();
|
||||
}
|
||||
|
||||
if let Err(err) = writer.write_all(&data) {
|
||||
debug!("writing data returned error: {err}");
|
||||
|
||||
reply.error(EIO);
|
||||
return;
|
||||
}
|
||||
|
||||
bytes_written += data.len();
|
||||
|
||||
reply.written(bytes_written as u32);
|
||||
|
||||
// TODO: update file size
|
||||
if offset + bytes_written as u64 > inode.size() {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(
|
||||
|
|
@ -395,14 +471,34 @@ impl Filesystem for FatFuse {
|
|||
_req: &fuser::Request<'_>,
|
||||
ino: u64,
|
||||
fh: u64,
|
||||
lock_owner: u64,
|
||||
_lock_owner: u64,
|
||||
reply: fuser::ReplyEmpty,
|
||||
) {
|
||||
debug!(
|
||||
"[Not Implemented] flush(ino: {:#x?}, fh: {}, lock_owner: {:?})",
|
||||
ino, fh, lock_owner
|
||||
);
|
||||
reply.error(ENOSYS);
|
||||
// debug!(
|
||||
// "[Not Implemented] flush(ino: {:#x?}, fh: {}, lock_owner: {:?})",
|
||||
// ino, fh, lock_owner
|
||||
// );
|
||||
// reply.error(ENOSYS);
|
||||
|
||||
debug!("flushing ino={ino} fh={fh}");
|
||||
|
||||
let Some(&found_ino) = self.ino_by_fh.get(&fh) else {
|
||||
debug!("expected fh {fh} to be mapped to ino {ino}, but not found instead");
|
||||
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
};
|
||||
|
||||
if found_ino != ino {
|
||||
debug!(
|
||||
"expected fh {fh} to be mapped to ino {ino}, but was mapped to {found_ino} instead"
|
||||
);
|
||||
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
}
|
||||
|
||||
reply.ok();
|
||||
}
|
||||
|
||||
fn release(
|
||||
|
|
@ -418,14 +514,14 @@ impl Filesystem for FatFuse {
|
|||
let Some(found_ino) = self.ino_by_fh.remove(&fh) else {
|
||||
debug!("tried to release fh {fh} with ino {ino}, but no ino was found in mapping");
|
||||
|
||||
reply.error(EINVAL);
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
};
|
||||
|
||||
if found_ino != ino {
|
||||
debug!("tried to release fh {fh} with ino {ino}, but found ino is {found_ino} instead");
|
||||
|
||||
reply.error(EIO);
|
||||
reply.error(EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -475,10 +571,12 @@ impl Filesystem for FatFuse {
|
|||
let Some(dir_inode) = self.get_inode_by_fh(fh) else {
|
||||
debug!("could not find inode accociated with fh {} (ino: {})", fh, ino);
|
||||
|
||||
reply.error(EINVAL);
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
};
|
||||
|
||||
let dir_inode = dir_inode.borrow();
|
||||
|
||||
if dir_inode.ino() != ino {
|
||||
debug!(
|
||||
"ino {} of inode associated with fh {} does not match given ino {}",
|
||||
|
|
@ -533,9 +631,11 @@ impl Filesystem for FatFuse {
|
|||
for dir_entry in dirs {
|
||||
let name = dir_entry.name_string();
|
||||
|
||||
let inode: &Inode =
|
||||
let inode =
|
||||
self.get_or_make_inode_by_dir_entry(&dir_entry, dir_ino, Rc::clone(&dir_path));
|
||||
|
||||
let inode = inode.borrow();
|
||||
|
||||
debug!("adding entry {} (ino: {})", name, inode.ino());
|
||||
if reply.add(ino, next_offset(), inode.kind().into(), name) {
|
||||
return;
|
||||
|
|
@ -571,17 +671,19 @@ impl Filesystem for FatFuse {
|
|||
let Some(ino) = self.ino_by_fh.remove(&fh) else {
|
||||
debug!("can't find inode {} by fh {}", ino, fh);
|
||||
|
||||
reply.error(EIO);
|
||||
reply.error(EBADF);
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(inode) = self.inode_table.get(&ino) else {
|
||||
let Some(inode) = self.get_inode(ino) else {
|
||||
debug!("ino {} not associated with an inode", ino);
|
||||
|
||||
reply.ok();
|
||||
return;
|
||||
};
|
||||
|
||||
let inode = inode.borrow();
|
||||
|
||||
if inode.ino() != ino {
|
||||
debug!(
|
||||
"inode with ino {}, associated with fh {}, does not have expected ino {}",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::cell::{LazyCell, RefCell};
|
||||
use std::rc::Rc;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::time::SystemTime;
|
||||
|
||||
use chrono::{NaiveDateTime, NaiveTime};
|
||||
use fat_bits::FatFs;
|
||||
use fat_bits::dir::DirEntry;
|
||||
use fat_bits::iter::ClusterChainReader;
|
||||
use fat_bits::iter::{ClusterChainReader, ClusterChainWriter};
|
||||
use fuser::FileAttr;
|
||||
use libc::{EISDIR, ENOTDIR};
|
||||
use log::debug;
|
||||
|
|
@ -27,12 +27,6 @@ fn get_random<T>() -> T
|
|||
where
|
||||
rand::distr::StandardUniform: rand::distr::Distribution<T>,
|
||||
{
|
||||
// RNG.with(|x| unsafe {
|
||||
// let rng = &mut (*x.get());
|
||||
|
||||
// rng.random::<u32>()
|
||||
// })
|
||||
|
||||
RNG.with(|rng| rng.borrow_mut().random())
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +47,9 @@ impl From<Kind> for fuser::FileType {
|
|||
|
||||
pub const ROOT_INO: u64 = 1;
|
||||
|
||||
pub type InodeRef = Rc<RefCell<Inode>>;
|
||||
pub type InodeWeak = Weak<RefCell<Inode>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub struct Inode {
|
||||
|
|
@ -63,7 +60,7 @@ pub struct Inode {
|
|||
|
||||
ref_count: u64,
|
||||
|
||||
parent_ino: u64,
|
||||
parent: Option<InodeRef>,
|
||||
|
||||
size: u64,
|
||||
block_size: u32,
|
||||
|
|
@ -105,7 +102,7 @@ impl Inode {
|
|||
uid: u32,
|
||||
gid: u32,
|
||||
path: impl Into<Rc<str>>,
|
||||
parent_ino: u64,
|
||||
parent: InodeRef,
|
||||
) -> Inode {
|
||||
assert!(dir_entry.is_file() || dir_entry.is_dir());
|
||||
|
||||
|
|
@ -142,9 +139,9 @@ impl Inode {
|
|||
ino,
|
||||
generation,
|
||||
ref_count: 0,
|
||||
parent_ino,
|
||||
parent: Some(parent),
|
||||
size: dir_entry.file_size() as u64,
|
||||
block_size: fat_fs.bpb().bytes_per_sector() as u32,
|
||||
block_size: fat_fs.bytes_per_sector() as u32,
|
||||
kind,
|
||||
read_only: dir_entry.is_readonly(),
|
||||
atime,
|
||||
|
|
@ -158,17 +155,15 @@ impl Inode {
|
|||
}
|
||||
|
||||
pub fn root_inode(fat_fs: &FatFs, uid: u32, gid: u32) -> Inode {
|
||||
// let generation = Self::new_generation();
|
||||
|
||||
let root_cluster = fat_fs.bpb().root_cluster().unwrap_or(0);
|
||||
let root_cluster = fat_fs.root_cluster().unwrap_or(0);
|
||||
|
||||
Inode {
|
||||
ino: 1,
|
||||
generation: 0,
|
||||
ino: ROOT_INO,
|
||||
generation: 0, // root cluster always has constant generation of 0
|
||||
ref_count: 0,
|
||||
parent_ino: ROOT_INO, // parent is self
|
||||
parent: None, // parent is self
|
||||
size: 0,
|
||||
block_size: fat_fs.bpb().bytes_per_sector() as u32,
|
||||
block_size: fat_fs.bytes_per_sector() as u32,
|
||||
kind: Kind::Dir,
|
||||
read_only: false,
|
||||
atime: SystemTime::UNIX_EPOCH,
|
||||
|
|
@ -225,8 +220,18 @@ impl Inode {
|
|||
self.ref_count
|
||||
}
|
||||
|
||||
pub fn parent_ino(&self) -> u64 {
|
||||
self.parent_ino
|
||||
pub fn parent(&self) -> Option<InodeRef> {
|
||||
self.parent.clone()
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn update_size(&mut self, new_size: u64) {
|
||||
self.size = new_size;
|
||||
|
||||
todo!("update dir entry")
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> Kind {
|
||||
|
|
@ -241,6 +246,10 @@ impl Inode {
|
|||
self.kind == Kind::Dir
|
||||
}
|
||||
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
self.read_only
|
||||
}
|
||||
|
||||
pub fn first_cluster(&self) -> u32 {
|
||||
self.first_cluster
|
||||
}
|
||||
|
|
@ -298,4 +307,12 @@ impl Inode {
|
|||
|
||||
Ok(fat_fs.file_reader(self.first_cluster()))
|
||||
}
|
||||
|
||||
pub fn file_writer<'a>(&'a self, fat_fs: &'a FatFs) -> Result<ClusterChainWriter<'a>, i32> {
|
||||
if self.is_dir() {
|
||||
return Err(EISDIR);
|
||||
}
|
||||
|
||||
Ok(fat_fs.file_writer(self.first_cluster()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
mod fuse;
|
||||
mod inode;
|
||||
|
||||
use std::cell::RefCell;
|
||||
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 log::{debug, error};
|
||||
|
||||
use crate::inode::Inode;
|
||||
use crate::inode::{Inode, InodeRef};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct FatFuse {
|
||||
|
|
@ -21,7 +22,7 @@ pub struct FatFuse {
|
|||
next_ino: u64,
|
||||
next_fh: u64,
|
||||
|
||||
inode_table: BTreeMap<u64, Inode>,
|
||||
inode_table: BTreeMap<u64, InodeRef>,
|
||||
|
||||
ino_by_first_cluster: BTreeMap<u32, u64>,
|
||||
ino_by_fh: BTreeMap<u64, u64>,
|
||||
|
|
@ -84,26 +85,28 @@ impl FatFuse {
|
|||
fh
|
||||
}
|
||||
|
||||
fn insert_inode(&mut self, inode: Inode) -> &mut Inode {
|
||||
fn insert_inode(&mut self, inode: Inode) -> InodeRef {
|
||||
let ino = inode.ino();
|
||||
let generation = inode.generation();
|
||||
let first_cluster = inode.first_cluster();
|
||||
|
||||
// let old_inode = self.inode_table.insert(ino, inode);
|
||||
|
||||
let inode = Rc::new(RefCell::new(inode));
|
||||
|
||||
let entry = self.inode_table.entry(ino);
|
||||
|
||||
let (new_inode, old_inode): (&mut Inode, Option<Inode>) = match entry {
|
||||
let (new_inode, old_inode) = match entry {
|
||||
std::collections::btree_map::Entry::Vacant(vacant_entry) => {
|
||||
let new_inode = vacant_entry.insert(inode);
|
||||
(new_inode, None)
|
||||
(Rc::clone(new_inode), None)
|
||||
}
|
||||
std::collections::btree_map::Entry::Occupied(occupied_entry) => {
|
||||
let entry_ref = occupied_entry.into_mut();
|
||||
|
||||
let old_inode = std::mem::replace(entry_ref, inode);
|
||||
|
||||
(entry_ref, Some(old_inode))
|
||||
(Rc::clone(entry_ref), Some(old_inode))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -113,6 +116,8 @@ impl FatFuse {
|
|||
);
|
||||
|
||||
if let Some(old_inode) = old_inode {
|
||||
let old_inode = old_inode.borrow();
|
||||
|
||||
debug!("ejected inode {} {}", old_inode.ino(), old_inode.generation());
|
||||
}
|
||||
|
||||
|
|
@ -122,22 +127,32 @@ 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);
|
||||
let path = new_inode.borrow().path();
|
||||
|
||||
if let Some(old_ino) = self.ino_by_path.insert(Rc::clone(&path), ino) {
|
||||
debug!("ejected old {} -> {} path to ino mapping", path, old_ino);
|
||||
}
|
||||
|
||||
new_inode
|
||||
}
|
||||
|
||||
fn drop_inode(&mut self, ino: u64) {
|
||||
debug!("dropping ino {}", ino);
|
||||
fn drop_inode(&mut self, inode: InodeRef) {
|
||||
let inode = inode.borrow();
|
||||
|
||||
let Some(inode) = self.inode_table.remove(&ino) else {
|
||||
debug!("tried to drop inode with ino {}, but was not in table", ino);
|
||||
let ino = inode.ino();
|
||||
|
||||
debug!("dropping inode {}", ino);
|
||||
|
||||
let Some(removed_inode) = self.inode_table.remove(&ino) else {
|
||||
error!("tried to drop inode with ino {}, but was not in table", ino);
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
if removed_inode.borrow().ino() != ino {
|
||||
error!("removed inode was not expected inode");
|
||||
}
|
||||
|
||||
let first_cluster = inode.first_cluster();
|
||||
|
||||
if first_cluster != 0 {
|
||||
|
|
@ -189,39 +204,28 @@ impl FatFuse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
fn get_inode(&self, ino: u64) -> Option<&InodeRef> {
|
||||
self.inode_table.get(&ino)
|
||||
}
|
||||
|
||||
fn get_inode_mut(&mut self, ino: u64) -> Option<&mut Inode> {
|
||||
self.inode_table.get_mut(&ino)
|
||||
}
|
||||
|
||||
fn get_or_make_inode_by_dir_entry(
|
||||
&mut self,
|
||||
dir_entry: &DirEntry,
|
||||
parent_ino: u64,
|
||||
parent_path: Rc<str>,
|
||||
) -> &mut Inode {
|
||||
) -> InodeRef {
|
||||
// try to find inode by first cluster first
|
||||
if dir_entry.first_cluster() != 0
|
||||
&& self
|
||||
.get_inode_by_first_cluster_mut(dir_entry.first_cluster())
|
||||
.is_some()
|
||||
&& let Some(inode) = self.get_inode_by_first_cluster(dir_entry.first_cluster())
|
||||
{
|
||||
return self
|
||||
.get_inode_by_first_cluster_mut(dir_entry.first_cluster())
|
||||
.unwrap();
|
||||
return inode;
|
||||
}
|
||||
|
||||
// try to find inode by path
|
||||
// mostly for empty files/directories which have a first cluster of 0
|
||||
|
||||
let path = {
|
||||
let mut path = parent_path.as_ref().to_owned();
|
||||
|
||||
|
|
@ -235,27 +239,25 @@ impl FatFuse {
|
|||
path
|
||||
};
|
||||
|
||||
if self.get_inode_by_path_mut(&path).is_some() {
|
||||
return self.get_inode_by_path_mut(&path).unwrap();
|
||||
if let Some(inode) = self.get_inode_by_path(&path) {
|
||||
return inode;
|
||||
}
|
||||
|
||||
// no inode found, make a new one
|
||||
let ino = self.next_ino();
|
||||
|
||||
let Some(parent_inode) = self.get_inode_mut(parent_ino) else {
|
||||
let Some(parent_inode) = self.get_inode(parent_ino).cloned() 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);
|
||||
let inode =
|
||||
Inode::new(&self.fat_fs, dir_entry, ino, self.uid, self.gid, path, parent_inode);
|
||||
|
||||
self.insert_inode(inode)
|
||||
}
|
||||
|
||||
pub fn get_inode_by_first_cluster(&self, first_cluster: u32) -> Option<&Inode> {
|
||||
pub fn get_inode_by_first_cluster(&self, first_cluster: u32) -> Option<InodeRef> {
|
||||
if first_cluster == 0 {
|
||||
debug!("trying to get inode by first cluster 0");
|
||||
|
||||
|
|
@ -265,7 +267,7 @@ impl FatFuse {
|
|||
let ino = self.ino_by_first_cluster.get(&first_cluster)?;
|
||||
|
||||
if let Some(inode) = self.inode_table.get(ino) {
|
||||
Some(inode)
|
||||
Some(Rc::clone(inode))
|
||||
} else {
|
||||
debug!(
|
||||
"first cluster {} is mapped to ino {}, but inode is not in table",
|
||||
|
|
@ -276,31 +278,10 @@ impl FatFuse {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_inode_by_first_cluster_mut(&mut self, first_cluster: u32) -> Option<&mut Inode> {
|
||||
if first_cluster == 0 {
|
||||
debug!("trying to get inode by first cluster 0");
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
let ino = self.ino_by_first_cluster.get(&first_cluster)?;
|
||||
|
||||
if let Some(inode) = self.inode_table.get_mut(ino) {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!(
|
||||
"first cluster {} is mapped to ino {}, but inode is not in table",
|
||||
first_cluster, ino
|
||||
);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inode_by_fh(&self, fh: u64) -> Option<&Inode> {
|
||||
pub fn get_inode_by_fh(&self, fh: u64) -> Option<InodeRef> {
|
||||
let ino = *self.ino_by_fh.get(&fh)?;
|
||||
|
||||
if let Some(inode) = self.get_inode(ino) {
|
||||
if let Some(inode) = self.get_inode(ino).cloned() {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!("fh {} is mapped to ino {}, but inode is not in table", fh, ino);
|
||||
|
|
@ -309,34 +290,10 @@ impl FatFuse {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_inode_by_fh_mut(&mut self, fh: u64) -> Option<&mut Inode> {
|
||||
let ino = *self.ino_by_fh.get(&fh)?;
|
||||
|
||||
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);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_inode_by_path(&self, path: &str) -> Option<&Inode> {
|
||||
pub fn get_inode_by_path(&self, path: &str) -> Option<InodeRef> {
|
||||
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) {
|
||||
if let Some(inode) = self.get_inode(ino).cloned() {
|
||||
Some(inode)
|
||||
} else {
|
||||
debug!("path {} is mapped to ino {}, but inode is not in table", path, ino);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue