ext2: cache sb as a regular block, avoid incoherency
This commit is contained in:
parent
fd9ea77adb
commit
3aea206cad
122
kernel/driver/fs/ext2/src/access.rs
Normal file
122
kernel/driver/fs/ext2/src/access.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
use libk::error::Error;
|
||||||
|
|
||||||
|
use crate::{BlockGroupDescriptor, Ext2Fs, ExtendedSuperblock, Inode};
|
||||||
|
|
||||||
|
impl Ext2Fs {
|
||||||
|
pub async fn with_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
||||||
|
&self,
|
||||||
|
index: u32,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
if index < 1 || index >= self.total_blocks {
|
||||||
|
return Err(Error::InvalidFile);
|
||||||
|
}
|
||||||
|
self.mapper
|
||||||
|
.try_with(self.block_address(index), mapper)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn with_block_mut<T, F: FnOnce(&mut [u8]) -> Result<T, Error>>(
|
||||||
|
&self,
|
||||||
|
index: u32,
|
||||||
|
write_size: usize,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
if index < 1 || index >= self.total_blocks {
|
||||||
|
return Err(Error::InvalidFile);
|
||||||
|
}
|
||||||
|
self.mapper
|
||||||
|
.try_with_mut(self.block_address(index), write_size, mapper)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn with_superblock_mut<T, F: FnOnce(&mut ExtendedSuperblock) -> Result<T, Error>>(
|
||||||
|
&self,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
let position = self.sb_position & !(self.block_size as u64 - 1);
|
||||||
|
let offset = (self.sb_position & (self.block_size as u64 - 1)) as usize;
|
||||||
|
|
||||||
|
self.mapper
|
||||||
|
.try_with_mut(position, size_of::<ExtendedSuperblock>(), |block| {
|
||||||
|
let sb = bytemuck::from_bytes_mut(
|
||||||
|
&mut block[offset..offset + size_of::<ExtendedSuperblock>()],
|
||||||
|
);
|
||||||
|
mapper(sb)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn with_inode_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
||||||
|
&self,
|
||||||
|
inode: &Inode,
|
||||||
|
block: u32,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
let block_index = self.inode_block_index(inode, block).await?;
|
||||||
|
self.with_block(block_index, mapper).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn with_inode_block_mut<T, F: FnOnce(&mut [u8]) -> Result<T, Error>>(
|
||||||
|
&self,
|
||||||
|
inode: &Inode,
|
||||||
|
block: u32,
|
||||||
|
write_size: usize,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
let block_index = self.inode_block_index(inode, block).await?;
|
||||||
|
self.with_block_mut(block_index, write_size, mapper).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn with_bgdt_entry<T, F: FnOnce(&BlockGroupDescriptor) -> Result<T, Error>>(
|
||||||
|
&self,
|
||||||
|
block_group: u32,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
let offset = block_group as usize * size_of::<BlockGroupDescriptor>();
|
||||||
|
let block = offset / self.block_size;
|
||||||
|
if block >= self.bgdt.block_count {
|
||||||
|
log::warn!("ext2: bgdt block out of bounds: {block}");
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
|
let offset_in_block = offset % self.block_size;
|
||||||
|
|
||||||
|
self.with_block(block as u32 + self.bgdt.base, |block| {
|
||||||
|
let descriptor = bytemuck::from_bytes(
|
||||||
|
&block[offset_in_block..offset_in_block + size_of::<BlockGroupDescriptor>()],
|
||||||
|
);
|
||||||
|
mapper(descriptor)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn with_bgdt_entry_mut<
|
||||||
|
T,
|
||||||
|
F: FnOnce(&mut BlockGroupDescriptor) -> Result<T, Error>,
|
||||||
|
>(
|
||||||
|
&self,
|
||||||
|
block_group: u32,
|
||||||
|
mapper: F,
|
||||||
|
) -> Result<T, Error> {
|
||||||
|
let offset = block_group as usize * size_of::<BlockGroupDescriptor>();
|
||||||
|
let block = offset / self.block_size;
|
||||||
|
if block >= self.bgdt.block_count {
|
||||||
|
log::warn!("ext2: bgdt block out of bounds: {block}");
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
|
let offset_in_block = offset % self.block_size;
|
||||||
|
|
||||||
|
self.with_block_mut(
|
||||||
|
block as u32 + self.bgdt.base,
|
||||||
|
size_of::<BlockGroupDescriptor>(),
|
||||||
|
|block| {
|
||||||
|
let descriptor = bytemuck::from_bytes_mut(
|
||||||
|
&mut block
|
||||||
|
[offset_in_block..offset_in_block + size_of::<BlockGroupDescriptor>()],
|
||||||
|
);
|
||||||
|
mapper(descriptor)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
@ -39,15 +39,11 @@ impl Ext2Fs {
|
|||||||
.await?
|
.await?
|
||||||
.expect("TODO: bgdt says there're things, but bitmap says there aren't");
|
.expect("TODO: bgdt says there're things, but bitmap says there aren't");
|
||||||
|
|
||||||
{
|
self.with_superblock_mut(|sb| {
|
||||||
let mut state = self.state.write();
|
superblock_mapper(sb);
|
||||||
superblock_mapper(&mut state.superblock);
|
Ok(())
|
||||||
state.dirty = true;
|
})
|
||||||
}
|
.await?;
|
||||||
|
|
||||||
if !self.cached {
|
|
||||||
self.flush_superblock().await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(group_index * group_item_count + no);
|
return Ok(group_index * group_item_count + no);
|
||||||
}
|
}
|
||||||
@ -69,16 +65,11 @@ impl Ext2Fs {
|
|||||||
descriptor.directories += 1;
|
descriptor.directories += 1;
|
||||||
}
|
}
|
||||||
descriptor.unallocated_inodes -= 1;
|
descriptor.unallocated_inodes -= 1;
|
||||||
log::info!("bg unallocated_inodes = {}", descriptor.unallocated_inodes);
|
|
||||||
Some((descriptor.inode_usage_bitmap, self.block_group_inode_count))
|
Some((descriptor.inode_usage_bitmap, self.block_group_inode_count))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|superblock| {
|
|superblock| {
|
||||||
superblock.total_unallocated_inodes -= 1;
|
superblock.total_unallocated_inodes -= 1;
|
||||||
log::info!(
|
|
||||||
"total_unallocated_inodes = {}",
|
|
||||||
superblock.total_unallocated_inodes
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@ -97,16 +88,11 @@ impl Ext2Fs {
|
|||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
descriptor.unallocated_blocks -= 1;
|
descriptor.unallocated_blocks -= 1;
|
||||||
log::info!("bg unallocated_blocks = {}", descriptor.unallocated_blocks);
|
|
||||||
Some((descriptor.block_usage_bitmap, self.block_group_block_count))
|
Some((descriptor.block_usage_bitmap, self.block_group_block_count))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|superblock| {
|
|superblock| {
|
||||||
superblock.total_unallocated_blocks -= 1;
|
superblock.total_unallocated_blocks -= 1;
|
||||||
log::info!(
|
|
||||||
"total_unallocated_blocks = {}",
|
|
||||||
superblock.total_unallocated_blocks
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -317,7 +317,7 @@ impl DirectoryNode {
|
|||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let fit_block = self
|
let fit_block = self
|
||||||
.fs
|
.fs
|
||||||
.with_inode_block_mut(&inode, i, 0, |block| {
|
.with_inode_block_mut(inode, i, 0, |block| {
|
||||||
let mut iter = DirentIterMut::new(&self.fs, &mut block[..], 0);
|
let mut iter = DirentIterMut::new(&self.fs, &mut block[..], 0);
|
||||||
if iter.try_fit(name, ino) {
|
if iter.try_fit(name, ino) {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -346,7 +346,7 @@ impl DirectoryNode {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
self.fs
|
self.fs
|
||||||
.with_inode_block_mut(&inode, block_index, self.fs.block_size, |block| {
|
.with_inode_block_mut(inode, block_index, self.fs.block_size, |block| {
|
||||||
block.fill(0);
|
block.fill(0);
|
||||||
|
|
||||||
// Place dirent
|
// Place dirent
|
||||||
@ -391,7 +391,7 @@ impl DirectoryNode {
|
|||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
self.fs
|
self.fs
|
||||||
.with_inode_block(&inode, i as _, |block| {
|
.with_inode_block(inode, i as _, |block| {
|
||||||
let iter = DirentIter::new(&self.fs, block, 0);
|
let iter = DirentIter::new(&self.fs, block, 0);
|
||||||
|
|
||||||
for (_, name, _) in iter {
|
for (_, name, _) in iter {
|
||||||
@ -439,7 +439,7 @@ impl DirectoryNode {
|
|||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let ino = self
|
let ino = self
|
||||||
.fs
|
.fs
|
||||||
.with_inode_block_mut(&inode, i as _, 0, |block| {
|
.with_inode_block_mut(inode, i as _, 0, |block| {
|
||||||
let mut iter = DirentIterMut::new(&self.fs, block, 0);
|
let mut iter = DirentIterMut::new(&self.fs, block, 0);
|
||||||
Ok(iter.remove(name))
|
Ok(iter.remove(name))
|
||||||
})
|
})
|
||||||
@ -482,7 +482,7 @@ impl DirectoryNode {
|
|||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let ino = self
|
let ino = self
|
||||||
.fs
|
.fs
|
||||||
.with_inode_block(&inode, i, |block| {
|
.with_inode_block(inode, i, |block| {
|
||||||
let iter = DirentIter::new(&self.fs, block, 0);
|
let iter = DirentIter::new(&self.fs, block, 0);
|
||||||
|
|
||||||
for (dirent, name, _) in iter {
|
for (dirent, name, _) in iter {
|
||||||
@ -531,7 +531,7 @@ impl DirectoryNode {
|
|||||||
|
|
||||||
let (entry_count, new_pos) = self
|
let (entry_count, new_pos) = self
|
||||||
.fs
|
.fs
|
||||||
.with_inode_block(&inode, index as u32, |block| {
|
.with_inode_block(inode, index as u32, |block| {
|
||||||
let mut pos = pos;
|
let mut pos = pos;
|
||||||
let mut entry_count = 0;
|
let mut entry_count = 0;
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ impl RegularNode {
|
|||||||
let amount = remaining.min(self.fs.block_size - block_offset);
|
let amount = remaining.min(self.fs.block_size - block_offset);
|
||||||
|
|
||||||
self.fs
|
self.fs
|
||||||
.with_inode_block_mut(&inode, block_index as u32, amount, |block| {
|
.with_inode_block_mut(inode, block_index as u32, amount, |block| {
|
||||||
block[block_offset..block_offset + amount]
|
block[block_offset..block_offset + amount]
|
||||||
.copy_from_slice(&buffer[offset..offset + amount]);
|
.copy_from_slice(&buffer[offset..offset + amount]);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -89,7 +89,7 @@ impl InodeAccess {
|
|||||||
let inode = self.inode_cache.get(self.ino).await?;
|
let inode = self.inode_cache.get(self.ino).await?;
|
||||||
let result = {
|
let result = {
|
||||||
let lock = inode.read();
|
let lock = inode.read();
|
||||||
mapper(&*lock)
|
mapper(&lock)
|
||||||
};
|
};
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ impl InodeAccess {
|
|||||||
let mut inode = self.inode_cache.get_mut(self.ino).await?;
|
let mut inode = self.inode_cache.get_mut(self.ino).await?;
|
||||||
let result = {
|
let result = {
|
||||||
let mut lock = inode.write();
|
let mut lock = inode.write();
|
||||||
mapper(&mut *lock)
|
mapper(&mut lock)
|
||||||
};
|
};
|
||||||
inode.put().await?;
|
inode.put().await?;
|
||||||
result
|
result
|
||||||
@ -227,7 +227,7 @@ impl InodeAccess {
|
|||||||
Err(error) => {
|
Err(error) => {
|
||||||
log::warn!("ext2: couldn't set up inode #{ino}: {error:?}");
|
log::warn!("ext2: couldn't set up inode #{ino}: {error:?}");
|
||||||
// TODO free the inode and flush it from the cache
|
// TODO free the inode and flush it from the cache
|
||||||
return Err(error);
|
Err(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,9 @@ use libk::{
|
|||||||
error::Error,
|
error::Error,
|
||||||
vfs::{Filesystem, FilesystemMountOption, NodeRef},
|
vfs::{Filesystem, FilesystemMountOption, NodeRef},
|
||||||
};
|
};
|
||||||
use libk_util::{sync::spin_rwlock::IrqSafeRwLock, OneTimeInit};
|
use libk_util::OneTimeInit;
|
||||||
|
|
||||||
|
pub mod access;
|
||||||
mod allocation;
|
mod allocation;
|
||||||
mod data;
|
mod data;
|
||||||
pub mod inode;
|
pub mod inode;
|
||||||
@ -30,11 +31,6 @@ pub use data::{BlockGroupDescriptor, Dirent, ExtendedSuperblock, Inode};
|
|||||||
use symlink::SymlinkNode;
|
use symlink::SymlinkNode;
|
||||||
use yggdrasil_abi::io::FileType;
|
use yggdrasil_abi::io::FileType;
|
||||||
|
|
||||||
struct State {
|
|
||||||
superblock: ExtendedSuperblock,
|
|
||||||
dirty: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Bgdt {
|
struct Bgdt {
|
||||||
base: u32,
|
base: u32,
|
||||||
entry_count: usize,
|
entry_count: usize,
|
||||||
@ -44,9 +40,8 @@ struct Bgdt {
|
|||||||
pub struct Ext2Fs {
|
pub struct Ext2Fs {
|
||||||
mapper: DeviceMapper,
|
mapper: DeviceMapper,
|
||||||
inode_cache: OneTimeInit<Arc<InodeCache>>,
|
inode_cache: OneTimeInit<Arc<InodeCache>>,
|
||||||
cached: bool,
|
|
||||||
|
|
||||||
state: IrqSafeRwLock<State>,
|
sb_position: u64,
|
||||||
bgdt: Bgdt,
|
bgdt: Bgdt,
|
||||||
|
|
||||||
total_inodes: u32,
|
total_inodes: u32,
|
||||||
@ -73,10 +68,6 @@ impl Filesystem for Ext2Fs {
|
|||||||
log::info!("ext2: flushing caches");
|
log::info!("ext2: flushing caches");
|
||||||
let mut last_err = None;
|
let mut last_err = None;
|
||||||
|
|
||||||
if let Err(error) = self.flush_superblock().await {
|
|
||||||
log::error!("ext2: superblock flush error: {error:?}");
|
|
||||||
last_err = Some(error);
|
|
||||||
}
|
|
||||||
if let Err(error) = self.flush_inode_cache().await {
|
if let Err(error) = self.flush_inode_cache().await {
|
||||||
log::error!("ext2: inode cache flush error {error:?}");
|
log::error!("ext2: inode cache flush error {error:?}");
|
||||||
last_err = Some(error);
|
last_err = Some(error);
|
||||||
@ -215,6 +206,12 @@ impl Ext2Fs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let block_size = 1024usize << superblock.block_size_log2;
|
let block_size = 1024usize << superblock.block_size_log2;
|
||||||
|
|
||||||
|
if data::SUPERBLOCK_OFFSET as usize + size_of::<ExtendedSuperblock>() > block_size {
|
||||||
|
log::error!("ext2: superblock struct crosses block boundary, cannot mount");
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
let bgdt_block_index = (data::SUPERBLOCK_OFFSET as usize).div_ceil(block_size) as u32;
|
let bgdt_block_index = (data::SUPERBLOCK_OFFSET as usize).div_ceil(block_size) as u32;
|
||||||
let bgdt_entry_count = superblock
|
let bgdt_entry_count = superblock
|
||||||
.total_blocks
|
.total_blocks
|
||||||
@ -277,12 +274,12 @@ impl Ext2Fs {
|
|||||||
|
|
||||||
mapper,
|
mapper,
|
||||||
inode_cache: OneTimeInit::new(),
|
inode_cache: OneTimeInit::new(),
|
||||||
cached,
|
|
||||||
|
|
||||||
state: IrqSafeRwLock::new(State {
|
sb_position: data::SUPERBLOCK_OFFSET,
|
||||||
superblock,
|
// state: IrqSafeRwLock::new(State {
|
||||||
dirty: false,
|
// superblock,
|
||||||
}),
|
// dirty: false,
|
||||||
|
// }),
|
||||||
bgdt,
|
bgdt,
|
||||||
|
|
||||||
required_features,
|
required_features,
|
||||||
@ -313,103 +310,6 @@ impl Ext2Fs {
|
|||||||
index as u64 * self.block_size as u64
|
index as u64 * self.block_size as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn with_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
|
||||||
&self,
|
|
||||||
index: u32,
|
|
||||||
mapper: F,
|
|
||||||
) -> Result<T, Error> {
|
|
||||||
if index < 1 || index >= self.total_blocks {
|
|
||||||
return Err(Error::InvalidFile);
|
|
||||||
}
|
|
||||||
self.mapper
|
|
||||||
.try_with(self.block_address(index), mapper)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn with_block_mut<T, F: FnOnce(&mut [u8]) -> Result<T, Error>>(
|
|
||||||
&self,
|
|
||||||
index: u32,
|
|
||||||
write_size: usize,
|
|
||||||
mapper: F,
|
|
||||||
) -> Result<T, Error> {
|
|
||||||
if index < 1 || index >= self.total_blocks {
|
|
||||||
return Err(Error::InvalidFile);
|
|
||||||
}
|
|
||||||
self.mapper
|
|
||||||
.try_with_mut(self.block_address(index), write_size, mapper)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn with_inode_block<T, F: FnOnce(&[u8]) -> Result<T, Error>>(
|
|
||||||
&self,
|
|
||||||
inode: &Inode,
|
|
||||||
block: u32,
|
|
||||||
mapper: F,
|
|
||||||
) -> Result<T, Error> {
|
|
||||||
let block_index = self.inode_block_index(inode, block).await?;
|
|
||||||
self.with_block(block_index, mapper).await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn with_inode_block_mut<T, F: FnOnce(&mut [u8]) -> Result<T, Error>>(
|
|
||||||
&self,
|
|
||||||
inode: &Inode,
|
|
||||||
block: u32,
|
|
||||||
write_size: usize,
|
|
||||||
mapper: F,
|
|
||||||
) -> Result<T, Error> {
|
|
||||||
let block_index = self.inode_block_index(inode, block).await?;
|
|
||||||
self.with_block_mut(block_index, write_size, mapper).await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn with_bgdt_entry<T, F: FnOnce(&BlockGroupDescriptor) -> Result<T, Error>>(
|
|
||||||
&self,
|
|
||||||
block_group: u32,
|
|
||||||
mapper: F,
|
|
||||||
) -> Result<T, Error> {
|
|
||||||
let offset = block_group as usize * size_of::<BlockGroupDescriptor>();
|
|
||||||
let block = offset / self.block_size;
|
|
||||||
if block >= self.bgdt.block_count {
|
|
||||||
log::warn!("ext2: bgdt block out of bounds: {block}");
|
|
||||||
return Err(Error::InvalidArgument);
|
|
||||||
}
|
|
||||||
let offset_in_block = offset % self.block_size;
|
|
||||||
|
|
||||||
self.with_block(block as u32 + self.bgdt.base, |block| {
|
|
||||||
let descriptor = bytemuck::from_bytes(
|
|
||||||
&block[offset_in_block..offset_in_block + size_of::<BlockGroupDescriptor>()],
|
|
||||||
);
|
|
||||||
mapper(descriptor)
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn with_bgdt_entry_mut<T, F: FnOnce(&mut BlockGroupDescriptor) -> Result<T, Error>>(
|
|
||||||
&self,
|
|
||||||
block_group: u32,
|
|
||||||
mapper: F,
|
|
||||||
) -> Result<T, Error> {
|
|
||||||
let offset = block_group as usize * size_of::<BlockGroupDescriptor>();
|
|
||||||
let block = offset / self.block_size;
|
|
||||||
if block >= self.bgdt.block_count {
|
|
||||||
log::warn!("ext2: bgdt block out of bounds: {block}");
|
|
||||||
return Err(Error::InvalidArgument);
|
|
||||||
}
|
|
||||||
let offset_in_block = offset % self.block_size;
|
|
||||||
|
|
||||||
self.with_block_mut(
|
|
||||||
block as u32 + self.bgdt.base,
|
|
||||||
size_of::<BlockGroupDescriptor>(),
|
|
||||||
|block| {
|
|
||||||
let descriptor = bytemuck::from_bytes_mut(
|
|
||||||
&mut block
|
|
||||||
[offset_in_block..offset_in_block + size_of::<BlockGroupDescriptor>()],
|
|
||||||
);
|
|
||||||
mapper(descriptor)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn inode(&self, ino: u32) -> Result<(u32, usize), Error> {
|
async fn inode(&self, ino: u32) -> Result<(u32, usize), Error> {
|
||||||
if ino < 1 || ino >= self.total_inodes {
|
if ino < 1 || ino >= self.total_inodes {
|
||||||
return Err(Error::InvalidFile);
|
return Err(Error::InvalidFile);
|
||||||
@ -491,25 +391,25 @@ impl Ext2Fs {
|
|||||||
self.inode_cache.get().flush().await
|
self.inode_cache.get().flush().await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn flush_superblock(&self) -> Result<(), Error> {
|
// pub async fn flush_superblock(&self) -> Result<(), Error> {
|
||||||
let state = self.state.read();
|
// let state = self.state.read();
|
||||||
if state.dirty {
|
// if state.dirty {
|
||||||
log::info!("Flushing superblock");
|
// log::info!("Flushing superblock");
|
||||||
log::info!(
|
// log::info!(
|
||||||
"inodes {} blocks {}",
|
// "inodes {} blocks {}",
|
||||||
state.superblock.total_unallocated_inodes,
|
// state.superblock.total_unallocated_inodes,
|
||||||
state.superblock.total_unallocated_blocks
|
// state.superblock.total_unallocated_blocks
|
||||||
);
|
// );
|
||||||
self.mapper
|
// self.mapper
|
||||||
.device()
|
// .device()
|
||||||
.write_exact(
|
// .write_exact(
|
||||||
data::SUPERBLOCK_OFFSET,
|
// data::SUPERBLOCK_OFFSET,
|
||||||
bytemuck::bytes_of(&state.superblock),
|
// bytemuck::bytes_of(&state.superblock),
|
||||||
)
|
// )
|
||||||
.await?;
|
// .await?;
|
||||||
}
|
// }
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
async fn read_index(&self, block_index: u32, index: usize) -> Result<u32, Error> {
|
async fn read_index(&self, block_index: u32, index: usize) -> Result<u32, Error> {
|
||||||
self.with_block(block_index, |block| {
|
self.with_block(block_index, |block| {
|
||||||
|
@ -48,12 +48,12 @@ impl SymlinkNode {
|
|||||||
// If length of symlink is lower than 60, data is stored directly in "block address"
|
// If length of symlink is lower than 60, data is stored directly in "block address"
|
||||||
// section of the inode
|
// section of the inode
|
||||||
if len < 60 {
|
if len < 60 {
|
||||||
let bytes = unsafe { Self::link_from_inode_blocks(&inode, len) };
|
let bytes = unsafe { Self::link_from_inode_blocks(inode, len) };
|
||||||
write.extend_from_slice(bytes);
|
write.extend_from_slice(bytes);
|
||||||
buf[..len].copy_from_slice(bytes);
|
buf[..len].copy_from_slice(bytes);
|
||||||
} else {
|
} else {
|
||||||
self.fs
|
self.fs
|
||||||
.with_inode_block(&inode, 0, |block| {
|
.with_inode_block(inode, 0, |block| {
|
||||||
write.extend_from_slice(&block[..len]);
|
write.extend_from_slice(&block[..len]);
|
||||||
buf[..len].copy_from_slice(&block[..len]);
|
buf[..len].copy_from_slice(&block[..len]);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -164,6 +164,13 @@ impl<A: PhysicalMemoryAllocator<Address = PhysicalAddress>> UncachedCache<A> {
|
|||||||
pos: u64,
|
pos: u64,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
) -> Result<T, Error> {
|
) -> Result<T, Error> {
|
||||||
|
if pos % self.block_size as u64 != 0 {
|
||||||
|
log::warn!(
|
||||||
|
"uncached: position {pos} is not a multiple of block size {}",
|
||||||
|
self.block_size
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
let mut data = PageBox::<_, A>::new_uninit_slice_in(self.block_size)?;
|
let mut data = PageBox::<_, A>::new_uninit_slice_in(self.block_size)?;
|
||||||
self.device.read_aligned(pos, data.as_slice_mut()).await?;
|
self.device.read_aligned(pos, data.as_slice_mut()).await?;
|
||||||
let result = mapper(unsafe { data.assume_init_slice_ref() })?;
|
let result = mapper(unsafe { data.assume_init_slice_ref() })?;
|
||||||
@ -176,6 +183,13 @@ impl<A: PhysicalMemoryAllocator<Address = PhysicalAddress>> UncachedCache<A> {
|
|||||||
size: usize,
|
size: usize,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
) -> Result<T, Error> {
|
) -> Result<T, Error> {
|
||||||
|
if pos % self.block_size as u64 != 0 {
|
||||||
|
log::warn!(
|
||||||
|
"uncached: position {pos} is not a multiple of block size {}",
|
||||||
|
self.block_size
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
let mut data = PageBox::<_, A>::new_uninit_slice_in(self.block_size)?;
|
let mut data = PageBox::<_, A>::new_uninit_slice_in(self.block_size)?;
|
||||||
// No need to read a block only to then fully rewrite it
|
// No need to read a block only to then fully rewrite it
|
||||||
if size != self.block_size {
|
if size != self.block_size {
|
||||||
@ -292,6 +306,13 @@ impl<A: PhysicalMemoryAllocator<Address = PhysicalAddress>> BlockCache<A> {
|
|||||||
block_position: u64,
|
block_position: u64,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
) -> Result<T, Error> {
|
) -> Result<T, Error> {
|
||||||
|
if block_position % self.block_size as u64 != 0 {
|
||||||
|
log::warn!(
|
||||||
|
"mapper: position {block_position} is not a multiple of block size {}",
|
||||||
|
self.block_size
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
let segment_position = block_position & !(self.segment_size as u64 - 1);
|
let segment_position = block_position & !(self.segment_size as u64 - 1);
|
||||||
let segment_offset = (block_position & (self.segment_size as u64 - 1)) as usize;
|
let segment_offset = (block_position & (self.segment_size as u64 - 1)) as usize;
|
||||||
let block = self.entry(segment_position).await?;
|
let block = self.entry(segment_position).await?;
|
||||||
@ -305,6 +326,13 @@ impl<A: PhysicalMemoryAllocator<Address = PhysicalAddress>> BlockCache<A> {
|
|||||||
_size: usize,
|
_size: usize,
|
||||||
mapper: F,
|
mapper: F,
|
||||||
) -> Result<T, Error> {
|
) -> Result<T, Error> {
|
||||||
|
if block_position % self.block_size as u64 != 0 {
|
||||||
|
log::warn!(
|
||||||
|
"mapper: position {block_position} is not a multiple of block size {}",
|
||||||
|
self.block_size
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
let segment_position = block_position & !(self.segment_size as u64 - 1);
|
let segment_position = block_position & !(self.segment_size as u64 - 1);
|
||||||
let segment_offset = (block_position & (self.segment_size as u64 - 1)) as usize;
|
let segment_offset = (block_position & (self.segment_size as u64 - 1)) as usize;
|
||||||
let block = self.entry(segment_position).await?;
|
let block = self.entry(segment_position).await?;
|
||||||
|
@ -343,13 +343,10 @@ impl File {
|
|||||||
|
|
||||||
/// Performs a device-specific request
|
/// Performs a device-specific request
|
||||||
pub fn device_request(&self, req: &mut DeviceRequest) -> Result<(), Error> {
|
pub fn device_request(&self, req: &mut DeviceRequest) -> Result<(), Error> {
|
||||||
match req {
|
if let DeviceRequest::IsTerminal(value) = req {
|
||||||
DeviceRequest::IsTerminal(value) => {
|
|
||||||
*value = self.is_terminal();
|
*value = self.is_terminal();
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::Char(f) => f.device.device_request(req),
|
Self::Char(f) => f.device.device_request(req),
|
||||||
|
@ -241,7 +241,7 @@ impl Node {
|
|||||||
|
|
||||||
if !self.flags.contains(NodeFlags::IN_MEMORY_PROPS) {
|
if !self.flags.contains(NodeFlags::IN_MEMORY_PROPS) {
|
||||||
// Update permissions in the real node
|
// Update permissions in the real node
|
||||||
common.set_metadata(self, &metadata)?;
|
common.set_metadata(self, metadata)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -255,7 +255,7 @@ impl Node {
|
|||||||
.metadata
|
.metadata
|
||||||
.get_or_try_insert_with(|| self.data_as_common().metadata(self))?;
|
.get_or_try_insert_with(|| self.data_as_common().metadata(self))?;
|
||||||
|
|
||||||
Ok(metadata.clone())
|
Ok(*metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO clarify directory size
|
// TODO clarify directory size
|
||||||
|
@ -54,8 +54,5 @@ pub fn set_current_directory(path: &str) -> Result<(), Error> {
|
|||||||
pub fn is_terminal(f: RawFd) -> bool {
|
pub fn is_terminal(f: RawFd) -> bool {
|
||||||
let mut option = DeviceRequest::IsTerminal(false);
|
let mut option = DeviceRequest::IsTerminal(false);
|
||||||
let res = unsafe { crate::sys::device_request(f, &mut option) };
|
let res = unsafe { crate::sys::device_request(f, &mut option) };
|
||||||
match (res, option) {
|
matches!((res, option), (Ok(()), DeviceRequest::IsTerminal(true)))
|
||||||
(Ok(()), DeviceRequest::IsTerminal(true)) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user