dev/block: add mutable block refs

This commit is contained in:
Mark Poliakov 2024-08-02 15:57:07 +03:00
parent b4fbc5cd4c
commit dfd45f0ab9

View File

@ -4,7 +4,7 @@ use alloc::sync::Arc;
use libk_mm::PageBox;
use libk_util::{
lru_hash_table::LruCache,
sync::spin_rwlock::{IrqSafeRwLock, IrqSafeRwLockReadGuard},
sync::spin_rwlock::{IrqSafeRwLock, IrqSafeRwLockReadGuard, IrqSafeRwLockWriteGuard},
};
use yggdrasil_abi::error::Error;
@ -22,6 +22,11 @@ pub struct CachedBlockRef {
lock: IrqSafeRwLockReadGuard<'static, CachedBlock>,
}
pub struct CachedBlockMut {
_entry: Arc<IrqSafeRwLock<CachedBlock>>,
lock: IrqSafeRwLockWriteGuard<'static, CachedBlock>,
}
pub struct BlockCache {
device: &'static dyn BlockDevice,
block_size: usize,
@ -70,11 +75,20 @@ impl BlockCache {
})))
}
pub async fn get<'a>(&'a self, address: u64) -> Result<CachedBlockRef, Error> {
async fn entry<'a>(
&'a self,
address: u64,
) -> Result<
MappedAsyncMutexGuard<
'a,
Arc<IrqSafeRwLock<CachedBlock>>,
LruCache<u64, Arc<IrqSafeRwLock<CachedBlock>>>,
>,
Error,
> {
debug_assert_eq!(address % self.block_size as u64, 0);
let entry: MappedAsyncMutexGuard<_, LruCache<u64, Arc<IrqSafeRwLock<CachedBlock>>>> = self
.cache
self.cache
.lock()
.await
.try_map_guard_async::<_, Error, _>(|cache: &'a mut LruCache<_, _>| async move {
@ -88,9 +102,19 @@ impl BlockCache {
Ok(value)
})
.await?;
.await
}
Ok(CachedBlockRef::new(entry.deref()))
pub async fn get<'a>(&'a self, address: u64) -> Result<CachedBlockRef, Error> {
self.entry(address)
.await
.map(|e| CachedBlockRef::new(e.deref()))
}
pub async fn get_mut<'a>(&'a self, address: u64) -> Result<CachedBlockMut, Error> {
self.entry(address)
.await
.map(|mut e| CachedBlockMut::new(e.deref_mut()))
}
pub async fn flush(&self) {
@ -118,6 +142,18 @@ impl CachedBlockRef {
}
}
impl CachedBlockMut {
pub fn new(entry: &Arc<IrqSafeRwLock<CachedBlock>>) -> Self {
let entry = entry.clone();
// Safety: ok, Arc instance is still held
let lock = unsafe { core::mem::transmute(entry.write()) };
Self {
lock,
_entry: entry,
}
}
}
impl Deref for CachedBlockRef {
type Target = PageBox<[u8]>;
@ -126,6 +162,20 @@ impl Deref for CachedBlockRef {
}
}
impl Deref for CachedBlockMut {
type Target = PageBox<[u8]>;
fn deref(&self) -> &Self::Target {
self.lock.deref()
}
}
impl DerefMut for CachedBlockMut {
fn deref_mut(&mut self) -> &mut Self::Target {
self.lock.deref_mut()
}
}
impl Deref for CachedBlock {
type Target = PageBox<[u8]>;