Skip to content

Commit

Permalink
Add cache to AtaBlockDevice (#396)
Browse files Browse the repository at this point in the history
* Add cache to AtaBlockDevice

* Add methods for cached blocks

* Rename cache index to hash

* Add ATA_CACHE_SIZE

* Refactor code
  • Loading branch information
vinc authored Aug 25, 2022
1 parent ec1fff6 commit d965a72
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/sys/fs/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
51 changes: 44 additions & 7 deletions src/sys/fs/block_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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(())
Expand Down Expand Up @@ -107,15 +107,19 @@ pub fn format_mem() {
}
}

const ATA_CACHE_SIZE: usize = 1024;

#[derive(Clone)]
pub struct AtaBlockDevice {
cache: [Option<(u32, Vec<u8>)>; ATA_CACHE_SIZE],
dev: sys::ata::Drive
}

impl AtaBlockDevice {
pub fn new(bus: u8, dsk: u8) -> Option<Self> {
sys::ata::Drive::open(bus, dsk).map(|dev| {
Self { dev }
let cache = [(); ATA_CACHE_SIZE].map(|_| None);
Self { dev, cache }
})
}

Expand All @@ -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 {
Expand Down

0 comments on commit d965a72

Please sign in to comment.