summaryrefslogtreecommitdiff
path: root/ayafs-core/src/memory
diff options
context:
space:
mode:
Diffstat (limited to 'ayafs-core/src/memory')
-rw-r--r--ayafs-core/src/memory/cached_block.rs79
-rw-r--r--ayafs-core/src/memory/cached_inode.rs8
-rw-r--r--ayafs-core/src/memory/dir_entry.rs14
3 files changed, 79 insertions, 22 deletions
diff --git a/ayafs-core/src/memory/cached_block.rs b/ayafs-core/src/memory/cached_block.rs
index c3d0338..24f08c0 100644
--- a/ayafs-core/src/memory/cached_block.rs
+++ b/ayafs-core/src/memory/cached_block.rs
@@ -4,6 +4,7 @@ use crate::AyaFS;
use lru::LruCache;
use std::num::NonZeroUsize;
use std::sync::Arc;
+use log::debug;
#[derive(Clone)]
pub struct CachedBlock<T: Block> {
@@ -27,20 +28,37 @@ pub fn convert<U: Block, T: Block>(input_block: &CachedBlock<U>) -> &CachedBlock
pub(crate) struct BlockCache<T: Block> {
device: Arc<dyn BlockDevice>,
cache: LruCache<usize, CachedBlock<T>>,
+ pub global_offset: usize,
}
impl<T: Block> BlockCache<T> {
- pub(crate) fn new(device: Arc<dyn BlockDevice>, cache_size: usize) -> Self {
+ pub(crate) fn new(device: Arc<dyn BlockDevice>, cache_size: usize, global_offset: usize) -> Self {
Self {
device,
cache: LruCache::new(NonZeroUsize::new(cache_size).unwrap()),
+ global_offset,
+ }
+ }
+
+ pub(crate) fn write_back(&self) {
+ for (_, cached_block) in self.cache.iter() {
+ if cached_block.dirty {
+ debug!("write_back: dirty block {}", self.global_offset + cached_block.index);
+ let block_buffer = unsafe {
+ let block_ptr = &cached_block.block as *const T as *const u8;
+ std::slice::from_raw_parts(block_ptr, std::mem::size_of::<T>())
+ };
+ self.device.write(self.global_offset + cached_block.index, block_buffer);
+ } else {
+ debug!("write_back: clean block {}", self.global_offset + cached_block.index);
+ }
}
}
pub(crate) fn load_block(&mut self, index: usize) -> bool {
if self.cache.contains(&index) == false {
let mut buffer = [0u8; BLOCK_SIZE];
- self.device.read(index, &mut buffer);
+ self.device.read(self.global_offset + index, &mut buffer);
let block: T = unsafe { std::mem::transmute_copy(&buffer) };
let cached_block = CachedBlock {
block,
@@ -50,10 +68,12 @@ impl<T: Block> BlockCache<T> {
if let Some((old_index, old_block)) = self.cache.push(index, cached_block) {
assert_ne!(old_index, index); // 只有 block 不在 cache 里的时候才会插入
if old_block.dirty {
- let old_block_ptr = &old_block.block as *const T as *mut u8;
- let old_block_buffer =
- unsafe { std::slice::from_raw_parts(old_block_ptr, BLOCK_SIZE) };
- self.device.write(old_index, old_block_buffer);
+ debug!("write_back: evicted dirty block {} while loading {}", self.global_offset + old_block.index, self.global_offset + index);
+ let old_block_buffer = unsafe {
+ let old_block_ptr = &old_block.block as *const T as *mut u8;
+ std::slice::from_raw_parts(old_block_ptr, BLOCK_SIZE)
+ };
+ self.device.write(self.global_offset + old_block.index, old_block_buffer);
}
}
}
@@ -64,21 +84,43 @@ impl<T: Block> BlockCache<T> {
/// 这个函数不应该返回 None
pub(crate) fn get_block<U: Block>(&mut self, index: usize) -> Option<&CachedBlock<U>> {
if !self.cache.contains(&index) {
+ debug!("get_block(global_block_id: {}) loading from disk", index + self.global_offset);
self.load_block(index);
}
- self.cache.get(&index).map(convert::<T, U>)
+
+ if let Some(block) = self.cache.get(&index) {
+ debug!("get_block(global_block_id: {}) found", index + self.global_offset);
+ Some(convert::<T, U>(block))
+ } else {
+ debug!("get_block(global_block_id: {}) not found", index + self.global_offset);
+ None
+ }
+ // debug!("get_block(global_block_id: {}) found", index + self.global_offset);
+ // self.cache.get(&index).map(convert::<T, U>)
}
/// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载.
/// 这个函数不应该返回 None
pub(crate) fn get_block_mut<U: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<U>> {
if !self.cache.contains(&index) {
+ debug!("get_block_mut(global_block_id: {}) loading from disk", index + self.global_offset);
self.load_block(index);
}
- self.cache.get_mut(&index).map(|block| {
+
+ if let Some(block) = self.cache.get_mut(&index) {
+ debug!("get_block_mut(global_block_id: {}) found", index + self.global_offset);
block.dirty = true;
- convert_mut::<T, U>(block)
- })
+ Some(convert_mut::<T, U>(block))
+ } else {
+ debug!("get_block_mut(global_block_id: {}) not found", index + self.global_offset);
+ None
+ }
+
+ // self.cache.get_mut(&index).map(|block| {
+ // debug!("get_block_mut(global_block_id: {}) found", index + self.global_offset);
+ // block.dirty = true;
+ // convert_mut::<T, U>(block)
+ // })
}
/// 向 LRU cache 中插入一个全新初始化的 block
@@ -94,7 +136,7 @@ impl<T: Block> BlockCache<T> {
let old_block_ptr = &old_block.block as *const T as *mut u8;
let old_block_buffer =
unsafe { std::slice::from_raw_parts(old_block_ptr, BLOCK_SIZE) };
- self.device.write(old_index, old_block_buffer);
+ self.device.write(self.global_offset + old_index, old_block_buffer);
}
}
}
@@ -115,15 +157,18 @@ impl<T: Block> BlockCache<T> {
if self.cache.contains(&block.index) {
let mut data_block = convert::<U, T>(&block).clone();
data_block.dirty = true; // TODO 需要把显式写回的都标记为 dirty 吗
- self.cache.push(block.index, data_block);
+ let (entry, _value) = self.cache.push(block.index, data_block).unwrap();
+ assert_eq!(entry, block.index);
+ debug!("update_block(global_block_id: {})", block.index + self.global_offset);
true
} else {
false
}
}
- fn pop(&mut self, entry: &usize) -> Option<CachedBlock<T>> {
- self.cache.pop(entry)
+ fn pop(&mut self, entry: usize) -> Option<CachedBlock<T>> {
+ debug!("pop_block(global_block_id: {})", entry + self.global_offset);
+ self.cache.pop(&entry)
}
}
@@ -134,9 +179,11 @@ impl AyaFS {
pub(crate) fn get_block<T: Block>(&mut self, index: usize) -> Option<&CachedBlock<T>> {
if self.data_bitmap.query(index) {
+ debug!("get_block(block_id: {}) found", index);
Some(self.cached_blocks.get_block::<T>(index).unwrap())
} else {
- self.cached_blocks.pop(&index);
+ debug!("get_block(block_id: {}) not exist", index);
+ self.cached_blocks.pop(index);
None
}
// self.data_bitmap
@@ -149,7 +196,7 @@ impl AyaFS {
if self.data_bitmap.query(index) {
Some(self.cached_blocks.get_block_mut::<T>(index).unwrap())
} else {
- self.cached_blocks.pop(&index);
+ self.cached_blocks.pop(index);
None
}
// self.data_bitmap
diff --git a/ayafs-core/src/memory/cached_inode.rs b/ayafs-core/src/memory/cached_inode.rs
index 2f26dde..70579c7 100644
--- a/ayafs-core/src/memory/cached_inode.rs
+++ b/ayafs-core/src/memory/cached_inode.rs
@@ -15,7 +15,7 @@ impl AyaFS {
) -> Option<(usize, &Inode)> {
self.inode_bitmap.allocate().map(|inode_index| {
self.get_inode_mut(inode_index).map(|inode| {
- *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ *inode = Inode::file(permissions, uid, gid, utils::time_now(), flags, 0, 0);
});
(inode_index, self.get_inode(inode_index).unwrap())
})
@@ -30,7 +30,7 @@ impl AyaFS {
) -> Option<(usize, &Inode)> {
self.inode_bitmap.allocate().map(|inode_index| {
self.get_inode_mut(inode_index).map(|inode| {
- *inode = Inode::symlink(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ *inode = Inode::symlink(permissions, uid, gid, utils::time_now(), flags, 0, 0);
});
(inode_index, self.get_inode(inode_index).unwrap())
})
@@ -48,7 +48,7 @@ impl AyaFS {
self.inode_bitmap.allocate().map(|inode_index| {
// 创建 Inode
let mut new_inode =
- Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0, 0);
+ Inode::directory(permissions, uid, gid, utils::time_now(), flags, 0, 0);
self.init_direntry_map(inode_index);
self.add_direntry(inode_index, &mut new_inode, inode_index, ".", 0x2)
.unwrap();
@@ -85,6 +85,7 @@ impl AyaFS {
_ => return Err(EIO),
}
}
+ // self.update_inode(inode_index, Inode::empty());
self.inode_bitmap.deallocate(inode_index);
Ok(true)
} else {
@@ -123,6 +124,7 @@ impl AyaFS {
if let Some(cached_block) = self.cached_inodes.get_block_mut::<InodeBlock>(block_index)
{
cached_block.block.inodes[offset / INODE_SIZE] = inode;
+ cached_block.dirty = true;
}
true
} else {
diff --git a/ayafs-core/src/memory/dir_entry.rs b/ayafs-core/src/memory/dir_entry.rs
index 55c67bd..3880f61 100644
--- a/ayafs-core/src/memory/dir_entry.rs
+++ b/ayafs-core/src/memory/dir_entry.rs
@@ -38,9 +38,11 @@ impl AyaFS {
match self.access_block::<DirectoryBlock>(inode, block_index_within_inode) {
Some(directory_block) => {
+ debug!("bitmap for block is {:#b} {:#b}", directory_block.block.occupancy[0], directory_block.block.occupancy[1]);
if directory_block.block.query(entry_index_within_block) {
let dir_entry = &directory_block.block.entries[entry_index_within_block];
let name = dir_entry.name();
+ debug!("loaded entry({:?}) for inode {}", name.as_os_str(), index);
dir_entry_map.insert(name, dir_entry.clone());
} else {
break;
@@ -70,7 +72,7 @@ impl AyaFS {
parent_inode: &mut Inode,
dir_entry_map: IndexMap<OsString, DirectoryEntry>,
) -> Result<(), c_int> {
- for (entry_index, (_, dir_entry)) in dir_entry_map.into_iter().enumerate() {
+ for (entry_index, (name, dir_entry)) in dir_entry_map.into_iter().enumerate() {
let block_index_within_inode = entry_index / 15;
let entry_index_within_block = entry_index % 15;
// 不够就新分配
@@ -89,7 +91,13 @@ impl AyaFS {
}
match self.access_block_mut::<DirectoryBlock>(parent_inode, block_index_within_inode) {
Some(directory_block) => {
+ if entry_index_within_block == 0 {
+ directory_block.block.reset();
+ }
+ directory_block.dirty = true;
+ debug!("entry {} (block {} offset {}) for inode {}, name {:?}", entry_index, block_index_within_inode, entry_index_within_block, _parent_index, name);
directory_block.block.allocate(entry_index_within_block);
+ debug!("bitmap for block is {:#b} {:#b}", directory_block.block.occupancy[0], directory_block.block.occupancy[1]);
directory_block.block.entries[entry_index_within_block] = dir_entry;
}
None => {
@@ -291,10 +299,10 @@ impl AyaFS {
} else {
let mut entry_index = 0;
while entry_index < parent_inode.size {
- if let Ok(entry) = self.get_direntry(parent_index, parent_inode, entry_index) {
+ if let Ok(entry) = self.get_direntry(parent_index, parent_inode, entry_index as u32) {
if entry.name() == name {
let inode = self.get_inode(entry.inode as usize).unwrap().clone();
- return Ok((entry.inode, entry_index, inode));
+ return Ok((entry.inode, entry_index as u32, inode));
}
}
entry_index += 1;