Cache inodes/dentries/ind blocks and group file block reads
This commit is contained in:
parent
e205e31797
commit
e55ad22620
@ -24,6 +24,7 @@ pub struct Ext2 {
|
||||
descriptor_table: BlockGroupDescriptorTable,
|
||||
inode_cache: RwLock<HashMap<u32, Inode>>,
|
||||
dentry_cache: RwLock<HashMap<PathBuf, DirEntryDisk>>,
|
||||
ind_block_cache: RwLock<HashMap<u32, Vec<u32>>>,
|
||||
}
|
||||
|
||||
impl Ext2 {
|
||||
@ -35,6 +36,7 @@ impl Ext2 {
|
||||
reader,
|
||||
inode_cache: RwLock::new(HashMap::new()),
|
||||
dentry_cache: RwLock::new(HashMap::new()),
|
||||
ind_block_cache: RwLock::new(HashMap::new()),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,12 @@ impl BlockReader {
|
||||
}
|
||||
|
||||
pub fn read_blocks(&self, block: u32, count: usize) -> io::Result<Cursor<Vec<u8>>> {
|
||||
let mut vec = vec![0; self.block_size * count];
|
||||
for block_no in block..(block + count as u32) {
|
||||
let data = self.read_block(block)?.into_inner();
|
||||
vec[((block_no - block) as usize * self.block_size)
|
||||
..(((block_no - block) as usize + 1) * self.block_size)]
|
||||
.copy_from_slice(&data);
|
||||
}
|
||||
let mut disk = &self.disk;
|
||||
let start = self.block_to_byte_offset(block);
|
||||
let size = self.block_size * count;
|
||||
let mut vec = vec![0; size];
|
||||
disk.seek(SeekFrom::Start(start))?;
|
||||
disk.read_exact(&mut vec)?;
|
||||
Ok(Cursor::new(vec))
|
||||
}
|
||||
|
||||
|
@ -47,10 +47,8 @@ impl File {
|
||||
}
|
||||
|
||||
pub fn read_at(&self, buf: &mut [u8], pos: u64, fs: &Ext2) -> io::Result<usize> {
|
||||
//println!("File::read_at(File {{pos: {}, inode: {}, ...}}, &mut [?; {}], {})", self.pos, self.inode.number, buf.len(), pos);
|
||||
let bytes_to_end = u64::from(self.inode.size_lower32).saturating_sub(pos);
|
||||
if bytes_to_end == 0 {
|
||||
//println!("File::read_at done, reporting 0 bytes read");
|
||||
return Ok(0);
|
||||
}
|
||||
let start_block = (pos / self.block_size as u64) as u32;
|
||||
@ -60,25 +58,39 @@ impl File {
|
||||
.reader
|
||||
.read_block_offset(
|
||||
self.inode
|
||||
.log_to_phys_block(&fs.reader, start_block)
|
||||
.log_to_phys_block(&fs, start_block)
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, "EOF reached"))?,
|
||||
offset as u32,
|
||||
)?
|
||||
.read(buf)?;
|
||||
let mut remaining_bytes = length.saturating_sub((self.block_size - offset) as u64);
|
||||
for block in (start_block + 1)..=u32::MAX {
|
||||
if remaining_bytes == 0 {
|
||||
break;
|
||||
};
|
||||
let _ =
|
||||
fs.reader
|
||||
.read_block(self.inode.log_to_phys_block(&fs.reader, block).ok_or_else(
|
||||
|| io::Error::new(io::ErrorKind::UnexpectedEof, "EOF reached"),
|
||||
)?)?
|
||||
.read(&mut buf[((length - remaining_bytes) as usize)..])?;
|
||||
remaining_bytes = remaining_bytes.saturating_sub(self.block_size as u64);
|
||||
let mut block = start_block + 1;
|
||||
while remaining_bytes != 0 {
|
||||
let mut chunk_start_block = self
|
||||
.inode
|
||||
.log_to_phys_block(&fs, block)
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::UnexpectedEof, "EOF reached"))?;
|
||||
let mut chunk_num_blocks = 1;
|
||||
block += 1;
|
||||
loop {
|
||||
if (chunk_num_blocks as usize * self.block_size) as u64 >= remaining_bytes {
|
||||
break;
|
||||
}
|
||||
let Some(phys_block) = self.inode.log_to_phys_block(&fs, block) else {
|
||||
break;
|
||||
};
|
||||
if phys_block != chunk_start_block + chunk_num_blocks {
|
||||
break;
|
||||
}
|
||||
chunk_num_blocks += 1;
|
||||
block += 1;
|
||||
}
|
||||
let _ = fs
|
||||
.reader
|
||||
.read_blocks(chunk_start_block, chunk_num_blocks as usize)?
|
||||
.read(&mut buf[((length - remaining_bytes) as usize)..])?;
|
||||
remaining_bytes = remaining_bytes.saturating_sub((self.block_size * chunk_num_blocks as usize) as u64);
|
||||
}
|
||||
//println!("File::read_at done, reporting {} bytes read", length - remaining_bytes);
|
||||
Ok((length - remaining_bytes) as usize)
|
||||
}
|
||||
}
|
||||
|
@ -156,19 +156,24 @@ impl Inode {
|
||||
Ok(ino)
|
||||
}
|
||||
|
||||
pub fn pointer_block_blocks(&self, block: u32, reader: &BlockReader) -> io::Result<Vec<u32>> {
|
||||
Ok(reader
|
||||
.read_block(block)?
|
||||
pub fn pointer_block_blocks(&self, block_no: u32, fs: &Ext2) -> io::Result<Vec<u32>> {
|
||||
if let Some(block) = fs.ind_block_cache.read().get(&block_no) {
|
||||
return Ok(block.clone());
|
||||
}
|
||||
let block = fs.reader
|
||||
.read_block(block_no)?
|
||||
.into_inner()
|
||||
.iter()
|
||||
.copied()
|
||||
.tuples::<(_, _, _, _)>()
|
||||
.map(|raw| u32::from_le_bytes([raw.0, raw.1, raw.2, raw.3]))
|
||||
.collect_vec())
|
||||
.collect_vec();
|
||||
fs.ind_block_cache.write().insert(block_no, block.clone());
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
pub fn log_to_phys_block(&self, reader: &BlockReader, block: u32) -> Option<u32> {
|
||||
let num_sing_indir = reader.block_size / 4;
|
||||
pub fn log_to_phys_block(&self, fs: &Ext2, block: u32) -> Option<u32> {
|
||||
let num_sing_indir = fs.reader.block_size / 4;
|
||||
let num_doub_indir = num_sing_indir * num_sing_indir;
|
||||
let num_trip_indir = num_sing_indir * num_doub_indir;
|
||||
if block < 12 {
|
||||
@ -179,7 +184,7 @@ impl Inode {
|
||||
}
|
||||
} else if block < (12 + num_sing_indir) as u32 {
|
||||
let blocks = self
|
||||
.pointer_block_blocks(self.singly_indirect_block_pointer, reader)
|
||||
.pointer_block_blocks(self.singly_indirect_block_pointer, fs)
|
||||
.ok()?;
|
||||
let block = blocks[(block - 12) as usize];
|
||||
if block == 0 {
|
||||
@ -192,10 +197,10 @@ impl Inode {
|
||||
let doub_indir_offset = (block as usize - base_block) / num_sing_indir;
|
||||
let sing_indir_offset = (block as usize - base_block) % num_sing_indir;
|
||||
let sing_indir_blocks = self
|
||||
.pointer_block_blocks(self.doubly_indirect_block_pointer, reader)
|
||||
.pointer_block_blocks(self.doubly_indirect_block_pointer, fs)
|
||||
.ok()?;
|
||||
let blocks = self
|
||||
.pointer_block_blocks(sing_indir_blocks[doub_indir_offset], reader)
|
||||
.pointer_block_blocks(sing_indir_blocks[doub_indir_offset], fs)
|
||||
.ok()?;
|
||||
let block = blocks[sing_indir_offset];
|
||||
if block == 0 {
|
||||
@ -211,13 +216,13 @@ impl Inode {
|
||||
let sing_indir_offset =
|
||||
((block as usize - base_block) % num_doub_indir) % num_sing_indir;
|
||||
let doub_indir_blocks = self
|
||||
.pointer_block_blocks(self.triply_indirect_block_pointer, reader)
|
||||
.pointer_block_blocks(self.triply_indirect_block_pointer, fs)
|
||||
.ok()?;
|
||||
let sing_indir_blocks = self
|
||||
.pointer_block_blocks(doub_indir_blocks[trip_indir_offset], reader)
|
||||
.pointer_block_blocks(doub_indir_blocks[trip_indir_offset], fs)
|
||||
.ok()?;
|
||||
let blocks = self
|
||||
.pointer_block_blocks(sing_indir_blocks[doub_indir_offset], reader)
|
||||
.pointer_block_blocks(sing_indir_blocks[doub_indir_offset], fs)
|
||||
.ok()?;
|
||||
let block = blocks[sing_indir_offset];
|
||||
if block == 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user