diff --git a/src/sys/fs/block.rs b/src/sys/fs/block.rs index 7eb684dcf..8ec04e0e3 100644 --- a/src/sys/fs/block.rs +++ b/src/sys/fs/block.rs @@ -42,7 +42,7 @@ impl Block { pub fn read(addr: u32) -> Self { let mut buf = [0; super::BLOCK_SIZE]; - if let Some(ref block_device) = *super::block_device::BLOCK_DEVICE.lock() { + if let Some(ref mut block_device) = *super::block_device::BLOCK_DEVICE.lock() { if block_device.read(addr, &mut buf).is_err() { debug!("MFS: could not read block {:#x}", addr); } diff --git a/src/sys/fs/block_device.rs b/src/sys/fs/block_device.rs index 7c6c9fde6..32ea35d56 100644 --- a/src/sys/fs/block_device.rs +++ b/src/sys/fs/block_device.rs @@ -16,14 +16,14 @@ pub enum BlockDevice { } pub trait BlockDeviceIO { - fn read(&self, addr: u32, buf: &mut [u8]) -> Result<(), ()>; + fn read(&mut self, addr: u32, buf: &mut [u8]) -> Result<(), ()>; fn write(&mut self, addr: u32, buf: &[u8]) -> Result<(), ()>; fn block_size(&self) -> usize; fn block_count(&self) -> usize; } impl BlockDeviceIO for BlockDevice { - fn read(&self, addr: u32, buf: &mut [u8]) -> Result<(), ()> { + fn read(&mut self, addr: u32, buf: &mut [u8]) -> Result<(), ()> { match self { BlockDevice::Mem(dev) => dev.read(addr, buf), BlockDevice::Ata(dev) => dev.read(addr, buf), @@ -70,7 +70,7 @@ impl MemBlockDevice { } impl BlockDeviceIO for MemBlockDevice { - fn read(&self, block_index: u32, buf: &mut [u8]) -> Result<(), ()> { + fn read(&mut self, block_index: u32, buf: &mut [u8]) -> Result<(), ()> { // TODO: check for overflow buf[..].clone_from_slice(&self.dev[block_index as usize][..]); Ok(()) @@ -107,15 +107,19 @@ pub fn format_mem() { } } +const ATA_CACHE_SIZE: usize = 1024; + #[derive(Clone)] pub struct AtaBlockDevice { + cache: [Option<(u32, Vec)>; ATA_CACHE_SIZE], dev: sys::ata::Drive } impl AtaBlockDevice { pub fn new(bus: u8, dsk: u8) -> Option { sys::ata::Drive::open(bus, dsk).map(|dev| { - Self { dev } + let cache = [(); ATA_CACHE_SIZE].map(|_| None); + Self { dev, cache } }) } @@ -124,15 +128,48 @@ impl AtaBlockDevice { self.block_size() * self.block_count() } */ + + fn hash(&self, block_addr: u32) -> usize { + (block_addr as usize) % self.cache.len() + } + + fn cached_block(&self, block_addr: u32) -> Option<&[u8]> { + let h = self.hash(block_addr); + if let Some((cached_addr, cached_buf)) = &self.cache[h] { + if block_addr == *cached_addr { + return Some(cached_buf); + } + } + None + } + + fn set_cached_block(&mut self, block_addr: u32, buf: &[u8]) { + let h = self.hash(block_addr); + self.cache[h] = Some((block_addr, buf.to_vec())); + } + + fn unset_cached_block(&mut self, block_addr: u32) { + let h = self.hash(block_addr); + self.cache[h] = None; + } } impl BlockDeviceIO for AtaBlockDevice { - fn read(&self, block_addr: u32, buf: &mut [u8]) -> Result<(), ()> { - sys::ata::read(self.dev.bus, self.dev.dsk, block_addr, buf) + fn read(&mut self, block_addr: u32, buf: &mut [u8]) -> Result<(), ()> { + if let Some(cached) = self.cached_block(block_addr) { + buf.copy_from_slice(cached); + return Ok(()); + } + + sys::ata::read(self.dev.bus, self.dev.dsk, block_addr, buf)?; + self.set_cached_block(block_addr, buf); + Ok(()) } fn write(&mut self, block_addr: u32, buf: &[u8]) -> Result<(), ()> { - sys::ata::write(self.dev.bus, self.dev.dsk, block_addr, buf) + sys::ata::write(self.dev.bus, self.dev.dsk, block_addr, buf)?; + self.unset_cached_block(block_addr); + Ok(()) } fn block_size(&self) -> usize {