dev/block: add mutable block refs
This commit is contained in:
parent
b4fbc5cd4c
commit
dfd45f0ab9
@ -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]>;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user