ext2: check for inode deletion before pulling from cache
This commit is contained in:
parent
68d0568af3
commit
17e2fba8b7
@ -241,6 +241,10 @@ impl Inode {
|
||||
unsafe { GroupId::from_raw(self.uid as _) }
|
||||
}
|
||||
|
||||
pub fn is_deleted(&self) -> bool {
|
||||
self.hard_links == 0
|
||||
}
|
||||
|
||||
pub fn metadata(&self, fs: &Ext2Fs, ino: u32) -> Metadata {
|
||||
Metadata {
|
||||
uid: self.user_id(),
|
||||
|
@ -170,19 +170,9 @@ impl DirectoryNode {
|
||||
|
||||
let child = InodeAccess::new(self.inode.cache().clone(), ino);
|
||||
|
||||
child.link().await?;
|
||||
let ty = child
|
||||
.amap_mut(async |child_inode| {
|
||||
// Get child inode type indicator which may or may not be used in the dirent
|
||||
let ty = child_inode
|
||||
.mode
|
||||
.dirent_indicator()
|
||||
.ok_or(Error::InvalidArgument)?;
|
||||
|
||||
child_inode.inc_hard_count();
|
||||
child_inode.dtime = 0;
|
||||
|
||||
Ok(ty)
|
||||
})
|
||||
.map(|inode| inode.mode.dirent_indicator().ok_or(Error::InvalidArgument))
|
||||
.await?;
|
||||
|
||||
// Insert the entry
|
||||
@ -195,7 +185,9 @@ impl DirectoryNode {
|
||||
// Otherwise, allocate a new block and extend the directory
|
||||
extend(inode, &self.fs, name, ino, ty).await
|
||||
})
|
||||
.await
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn prepare_for_removal(&self) -> Result<(), Error> {
|
||||
|
@ -46,7 +46,7 @@ impl InodeAccess {
|
||||
&self,
|
||||
mapper: F,
|
||||
) -> Result<T, Error> {
|
||||
let inode = self.inode_cache.entry(self.ino).await?;
|
||||
let inode = self.inode_cache.get(self.ino).await?;
|
||||
let lock = inode.read();
|
||||
mapper(&lock.inode)
|
||||
}
|
||||
@ -55,7 +55,7 @@ impl InodeAccess {
|
||||
&self,
|
||||
mapper: F,
|
||||
) -> Result<T, Error> {
|
||||
let inode = self.inode_cache.entry(self.ino).await?;
|
||||
let inode = self.inode_cache.get(self.ino).await?;
|
||||
let mut lock = inode.write();
|
||||
let result = mapper(&mut lock.inode);
|
||||
self.inode_cache.put(self.ino, &mut lock).await?;
|
||||
@ -66,7 +66,7 @@ impl InodeAccess {
|
||||
&self,
|
||||
mapper: F,
|
||||
) -> Result<T, Error> {
|
||||
let inode = self.inode_cache.entry(self.ino).await?;
|
||||
let inode = self.inode_cache.get(self.ino).await?;
|
||||
let lock = inode.read();
|
||||
mapper(&lock.inode).await
|
||||
}
|
||||
@ -75,7 +75,7 @@ impl InodeAccess {
|
||||
&self,
|
||||
mapper: F,
|
||||
) -> Result<T, Error> {
|
||||
let inode = self.inode_cache.entry(self.ino).await?;
|
||||
let inode = self.inode_cache.get(self.ino).await?;
|
||||
let mut lock = inode.write();
|
||||
let result = mapper(&mut lock.inode).await;
|
||||
self.inode_cache.put(self.ino, &mut lock).await?;
|
||||
@ -176,6 +176,7 @@ impl InodeAccess {
|
||||
) -> Result<NodeRef, Error> {
|
||||
log::info!("ext2: allocated inode #{ino}");
|
||||
|
||||
let cache = fs.inode_cache.get().clone();
|
||||
let now = real_time().seconds as u32;
|
||||
|
||||
let mut imode = InodeMode::default_for_type(ty);
|
||||
@ -193,7 +194,7 @@ impl InodeAccess {
|
||||
)
|
||||
.await?;
|
||||
|
||||
let this = InodeAccess::new(fs.inode_cache.get().clone(), ino);
|
||||
let this = InodeAccess::new(cache, ino);
|
||||
let fs = fs.clone();
|
||||
let node = match ty {
|
||||
FileType::Directory => DirectoryNode::create(fs, this, parent_ino).await?,
|
||||
@ -205,6 +206,15 @@ impl InodeAccess {
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
pub async fn link(&self) -> Result<(), Error> {
|
||||
let inode = self.inode_cache.entry(self.ino, true).await?;
|
||||
let mut inode = inode.write();
|
||||
inode.hard_links += 1;
|
||||
inode.dtime = 0;
|
||||
self.inode_cache.put(self.ino, &mut inode).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn allocate(
|
||||
fs: &Arc<Ext2Fs>,
|
||||
ty: FileType,
|
||||
@ -256,22 +266,35 @@ impl InodeCache {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn fetch_inode(&self, ino: u32) -> Result<Arc<IrqSafeRwLock<InodeHolder>>, Error> {
|
||||
async fn fetch_inode(
|
||||
&self,
|
||||
ino: u32,
|
||||
allow_deleted: bool,
|
||||
) -> Result<Arc<IrqSafeRwLock<InodeHolder>>, Error> {
|
||||
let inode = self.fs.read_inode(ino).await?;
|
||||
|
||||
if inode.is_deleted() && !allow_deleted {
|
||||
return Err(Error::DoesNotExist);
|
||||
}
|
||||
|
||||
Ok(Arc::new(IrqSafeRwLock::new(InodeHolder {
|
||||
inode,
|
||||
dirty: false,
|
||||
})))
|
||||
}
|
||||
|
||||
async fn entry(&self, ino: u32) -> Result<Arc<IrqSafeRwLock<InodeHolder>>, Error> {
|
||||
async fn entry(
|
||||
&self,
|
||||
ino: u32,
|
||||
allow_deleted: bool,
|
||||
) -> Result<Arc<IrqSafeRwLock<InodeHolder>>, Error> {
|
||||
if ino < 1 || ino > self.fs.total_inodes {
|
||||
return Err(Error::InvalidFile);
|
||||
}
|
||||
|
||||
let mut lock = self.cache.lock().await;
|
||||
let (value, evicted) = lock
|
||||
.try_get_or_insert_with_async(ino, || self.fetch_inode(ino))
|
||||
.try_get_or_insert_with_async(ino, || self.fetch_inode(ino, allow_deleted))
|
||||
.await?;
|
||||
let value = value.clone();
|
||||
|
||||
@ -284,6 +307,10 @@ impl InodeCache {
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
async fn get(&self, ino: u32) -> Result<Arc<IrqSafeRwLock<InodeHolder>>, Error> {
|
||||
self.entry(ino, false).await
|
||||
}
|
||||
|
||||
async fn put(&self, ino: u32, holder: &mut InodeHolder) -> Result<(), Error> {
|
||||
if self.synchronous {
|
||||
// Immediately write-back
|
||||
|
@ -272,10 +272,6 @@ impl Ext2Fs {
|
||||
inode_cache: OneTimeInit::new(),
|
||||
|
||||
sb_position: data::SUPERBLOCK_OFFSET,
|
||||
// state: IrqSafeRwLock::new(State {
|
||||
// superblock,
|
||||
// dirty: false,
|
||||
// }),
|
||||
bgdt,
|
||||
|
||||
required_features,
|
||||
|
Loading…
x
Reference in New Issue
Block a user