From 4c34414b26bf71e747ea3ecb2586645bab4aba52 Mon Sep 17 00:00:00 2001
From: Chuyan Zhang <me@zcy.moe>
Date: Fri, 1 Dec 2023 19:42:13 -0800
Subject: Multiple bugfix, it works!

---
 ayafs-core/Cargo.toml                   |   7 +-
 ayafs-core/src/bin/main.rs              |   9 +--
 ayafs-core/src/bin/mem_run.rs           |  43 +++++++++++
 ayafs-core/src/block_device/disk.rs     |  10 ++-
 ayafs-core/src/disk/allocation.rs       |  14 +++-
 ayafs-core/src/disk/bitmap.rs           |  40 ++++++++++-
 ayafs-core/src/disk/block.rs            |  44 ++++++------
 ayafs-core/src/disk/inode.rs            |  17 +----
 ayafs-core/src/filesystem/trait_impl.rs | 100 ++++++++++++++------------
 ayafs-core/src/lib.rs                   | 124 ++++++++++++++++++++++++++++----
 ayafs-core/src/memory/cached_block.rs   |  79 +++++++++++++++-----
 ayafs-core/src/memory/cached_inode.rs   |   8 ++-
 ayafs-core/src/memory/dir_entry.rs      |  14 +++-
 ayafs-core/src/tests/common/mod.rs      |   3 +-
 ayafs-core/src/tests/mod.rs             |   1 -
 ayafs-core/src/utils/constants.rs       |   1 -
 ayafs-core/src/utils/mod.rs             |  15 +---
 17 files changed, 388 insertions(+), 141 deletions(-)
 create mode 100644 ayafs-core/src/bin/mem_run.rs
 delete mode 100644 ayafs-core/src/utils/constants.rs

(limited to 'ayafs-core')

diff --git a/ayafs-core/Cargo.toml b/ayafs-core/Cargo.toml
index 8e12bf5..f4d0d38 100644
--- a/ayafs-core/Cargo.toml
+++ b/ayafs-core/Cargo.toml
@@ -12,6 +12,10 @@ path = "src/lib.rs"
 name = "ayafs_cli"
 path = "src/bin/main.rs"
 
+[[bin]]
+name = "ayafs_mem"
+path = "src/bin/mem_run.rs"
+
 [dependencies]
 and_then_some = "1.0.0"
 bitflags = "2.4.1"
@@ -22,4 +26,5 @@ indexmap = "2.1.0"
 libc = "0.2.150"
 log = "0.4.20"
 lru = "0.12.1"
-users = "0.11.0"
+static_assertions = "1.1.0"
+users = "0.11.0"
\ No newline at end of file
diff --git a/ayafs-core/src/bin/main.rs b/ayafs-core/src/bin/main.rs
index 25504b9..a2d838c 100644
--- a/ayafs-core/src/bin/main.rs
+++ b/ayafs-core/src/bin/main.rs
@@ -9,6 +9,7 @@ use aya::block_device::disk::Disk;
 #[derive(Parser, Debug)]
 #[command(author, version, about)]
 struct Args {
+    device_path: Option<String>,
     mount_point: Option<String>,
     #[arg(short, action = clap::ArgAction::Count)]
     verbosity: u8,
@@ -20,6 +21,7 @@ struct Args {
 
 fn main() {
     let args = Args::parse();
+    let device_path = args.device_path.unwrap();
     let mount_point = args.mount_point.unwrap();
     let verbosity = args.verbosity;
     let log_level = match verbosity {
@@ -36,9 +38,8 @@ fn main() {
         MountOption::AutoUnmount,
         MountOption::AllowRoot,
     ];
-    let disk = Arc::new(Disk::new(PathBuf::from("/dev/nvme0n1p4")));
-    // let disk = Arc::new(MemoryDisk::new(16384));
-    let filesystem = AyaFS::new(disk, 7864320);
-
+    let disk = Arc::new(Disk::new(PathBuf::from(device_path)));
+    let filesystem = AyaFS::load(disk);
+    
     fuser::mount2(filesystem, mount_point, &options).unwrap();
 }
\ No newline at end of file
diff --git a/ayafs-core/src/bin/mem_run.rs b/ayafs-core/src/bin/mem_run.rs
new file mode 100644
index 0000000..7ba6f4e
--- /dev/null
+++ b/ayafs-core/src/bin/mem_run.rs
@@ -0,0 +1,43 @@
+use std::sync::Arc;
+use clap::Parser;
+use fuser::MountOption;
+use log::LevelFilter;
+use users::{get_current_gid, get_current_uid};
+use aya::AyaFS;
+use aya::block_device::memory_disk::MemoryDisk;
+
+#[derive(Parser, Debug)]
+#[command(author, version, about)]
+struct Args {
+    mount_point: Option<String>,
+    #[arg(short, action = clap::ArgAction::Count)]
+    verbosity: u8,
+    #[arg(long)]
+    auto_unmount: bool,
+    #[arg(long)]
+    allow_root: bool,
+}
+
+fn main() {
+    let args = Args::parse();
+    let mount_point = args.mount_point.unwrap();
+    let verbosity = args.verbosity;
+    let log_level = match verbosity {
+        0 => LevelFilter::Error,
+        1 => LevelFilter::Warn,
+        2 => LevelFilter::Info,
+        3 => LevelFilter::Debug,
+        _ => LevelFilter::Trace,
+    };
+    env_logger::builder().filter_level(log_level).init();
+    let options = vec![
+        // MountOption::RO,
+        MountOption::FSName("hello".to_string()),
+        MountOption::AutoUnmount,
+        MountOption::AllowRoot,
+    ];
+    let disk = Arc::new(MemoryDisk::new(16384));
+    let filesystem = AyaFS::new(disk, 16384, get_current_uid(), get_current_gid());
+
+    fuser::mount2(filesystem, mount_point, &options).unwrap();
+}
\ No newline at end of file
diff --git a/ayafs-core/src/block_device/disk.rs b/ayafs-core/src/block_device/disk.rs
index d2beee9..9e9b6bc 100644
--- a/ayafs-core/src/block_device/disk.rs
+++ b/ayafs-core/src/block_device/disk.rs
@@ -2,22 +2,22 @@ use crate::block_device::{BlockDevice, BLOCK_SIZE};
 use std::cell::RefCell;
 use std::fs::File;
 use std::io::{Read, Seek, SeekFrom, Write};
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
+use log::debug;
 
 pub struct Disk {
+    #[allow(unused)]
     disk_path: PathBuf,
     device: RefCell<File>,
 }
 
 impl Disk {
     pub fn new(disk_path: PathBuf) -> Self {
-
         let device = File::options()
             .read(true)
             .write(true)
             .open(disk_path.as_path())
             .unwrap();
-        // let device = File::open(disk_path.as_path()).unwrap();
         Self {
             disk_path,
             device: RefCell::new(device),
@@ -27,6 +27,7 @@ impl Disk {
 
 impl BlockDevice for Disk {
     fn read(&self, block_id: usize, buffer: &mut [u8]) {
+        assert_eq!(buffer.len(), BLOCK_SIZE);
         let mut device = self.device.borrow_mut();
         device
             .seek(SeekFrom::Start((block_id * BLOCK_SIZE) as u64))
@@ -34,9 +35,11 @@ impl BlockDevice for Disk {
         device
             .read_exact(buffer)
             .expect("Failed to read 4096 bytes!");
+        debug!("disk::read block {}", block_id);
     }
 
     fn write(&self, block_id: usize, buffer: &[u8]) {
+        assert_eq!(buffer.len(), BLOCK_SIZE);
         let mut device = self.device.borrow_mut();
         device
             .seek(SeekFrom::Start((block_id * BLOCK_SIZE) as u64))
@@ -44,5 +47,6 @@ impl BlockDevice for Disk {
         device
             .write_all(buffer)
             .expect("Unable to write 4096 bytes!");
+        debug!("disk::write block {}", block_id);
     }
 }
diff --git a/ayafs-core/src/disk/allocation.rs b/ayafs-core/src/disk/allocation.rs
index a187fad..6b7167a 100644
--- a/ayafs-core/src/disk/allocation.rs
+++ b/ayafs-core/src/disk/allocation.rs
@@ -255,6 +255,7 @@ impl AyaFS {
         Ok(())
     }
 
+    #[allow(unused)]
     /// 从 inode 中删去最后一个 block
     pub(crate) fn deallocate_block_for(&mut self, inode: &mut Inode) -> Option<u32> {
         // 如果 triple indirect 块存在, 则尝试从中销毁一个块
@@ -300,6 +301,7 @@ impl AyaFS {
         None
     }
 
+    #[allow(unused)]
     fn deallocate_from_triple_indirect(&mut self, triple_indirect_entry: u32) -> Option<u32> {
         let triple_indirect_entry = triple_indirect_entry as usize;
         if let Some(triple_indirect_block) = self
@@ -339,6 +341,7 @@ impl AyaFS {
         None
     }
 
+    #[allow(unused)]
     fn deallocate_from_double_indirect(&mut self, double_indirect_entry: u32) -> Option<u32> {
         let double_indirect_entry = double_indirect_entry as usize;
         if let Some(double_indirect_block) = self
@@ -373,6 +376,7 @@ impl AyaFS {
         None
     }
 
+    #[allow(unused)]
     fn deallocate_from_indirect(&mut self, indirect_entry: u32) -> Option<u32> {
         let indirect_entry = indirect_entry as usize;
         if let Some(indirect_block) = self
@@ -521,6 +525,11 @@ impl AyaFS {
     ) -> Option<&CachedBlock<T>> {
         self.get_block_index(inode, block_index_within_inode)
             .map(|block_index| {
+                debug!(
+                    "access_block(index: {}) found with global index {}",
+                    block_index_within_inode,
+                    block_index,
+                );
                 self.get_block::<T>(block_index).unwrap() // 可以 unwrap 吧这里 ??
             })
     }
@@ -533,8 +542,9 @@ impl AyaFS {
         self.get_block_index(inode, block_index_within_inode)
             .map(|block_index| {
                 debug!(
-                    "access_block_mut(index: {}) found",
-                    block_index_within_inode
+                    "access_block_mut(index: {}) found with global index {}",
+                    block_index_within_inode,
+                    block_index,
                 );
                 self.get_block_mut::<T>(block_index).unwrap() // 可以 unwrap 吧这里 ??
             })
diff --git a/ayafs-core/src/disk/bitmap.rs b/ayafs-core/src/disk/bitmap.rs
index b68c341..cf7eae5 100644
--- a/ayafs-core/src/disk/bitmap.rs
+++ b/ayafs-core/src/disk/bitmap.rs
@@ -6,22 +6,59 @@ pub struct Bitmap {
     pub length: usize,
     pub device: Arc<dyn BlockDevice>,
     pub data: Vec<u8>,
+    pub count: u64,
 }
 
 impl Bitmap {
-    pub(crate) fn new(starting_block: usize, length: usize, device: Arc<dyn BlockDevice>) -> Self {
+    pub(crate) fn new(starting_block: usize, length: usize, device: Arc<dyn BlockDevice>, count: u64) -> Self {
         Self {
             starting_block,
             length,
             device,
             data: vec![0u8; length * BLOCK_SIZE],
+            count,
         }
     }
+
+    pub(crate) fn load(starting_block: usize, length: usize, device: Arc<dyn BlockDevice>, count: u64) -> Self {
+        let mut data = vec![0u8; length * BLOCK_SIZE];
+        for id in 0 .. length {
+            let block_id = starting_block + id;
+            device.read(block_id, &mut data[id * BLOCK_SIZE .. (id + 1) * BLOCK_SIZE]);
+        }
+        Self {
+            starting_block,
+            length,
+            device,
+            data,
+            count,
+        }
+    }
+
+    pub(crate) fn write_back(&self) {
+        for id in 0 .. self.length {
+            let block_id = self.starting_block + id;
+            self.device.write(block_id, &self.data[id * BLOCK_SIZE .. (id + 1) * BLOCK_SIZE]);
+        }
+    }
+
+    // Allocate, but doesn't modify self.
+    pub(crate) fn peek(&self) -> Option<usize> {
+        for (i, byte) in self.data.iter().enumerate() {
+            let leading_ones = byte.leading_ones();
+            if leading_ones != 8 {
+                return Some(i * 8 + leading_ones as usize);
+            }
+        }
+        None
+    }
+
     pub(crate) fn allocate(&mut self) -> Option<usize> {
         for (i, byte) in self.data.iter_mut().enumerate() {
             let leading_ones = byte.leading_ones();
             if leading_ones != 8 {
                 *byte |= (1 << (7 - leading_ones)) as u8;
+                self.count += 1;
                 return Some(i * 8 + leading_ones as usize);
             }
         }
@@ -39,6 +76,7 @@ impl Bitmap {
     pub(crate) fn deallocate(&mut self, index: usize) -> bool {
         if self.query(index) {
             let mask = !(1u8 << (7 - index % 8));
+            self.count -= 1;
             self.data[index / 8] &= mask;
             true
         } else {
diff --git a/ayafs-core/src/disk/block.rs b/ayafs-core/src/disk/block.rs
index 76769b9..e48385d 100644
--- a/ayafs-core/src/disk/block.rs
+++ b/ayafs-core/src/disk/block.rs
@@ -10,7 +10,10 @@ pub struct SuperBlock {
     pub(crate) inode_bitmap_block_number: u64,
     pub(crate) inode_block_number: u64,
     pub(crate) data_block_number: u64,
-    padding: [u8; 4064],
+    pub(crate) total_block_number: u64,
+    pub(crate) used_inode_number: u64,
+    pub(crate) used_block_number: u64,
+    padding: [u8; 4040],
 }
 
 impl SuperBlock {
@@ -19,13 +22,19 @@ impl SuperBlock {
         inode_bitmap_block_number: usize,
         inode_block_number: usize,
         data_block_number: usize,
+        total_block_number: usize,
+        used_inode_number: u64,
+        used_block_number: u64,
     ) -> Self {
         Self {
             data_bitmap_block_number: data_bitmap_block_number as u64,
             inode_bitmap_block_number: inode_bitmap_block_number as u64,
             inode_block_number: inode_block_number as u64,
             data_block_number: data_block_number as u64,
-            padding: [0; 4064],
+            total_block_number: total_block_number as u64,
+            used_inode_number,
+            used_block_number,
+            padding: [0; 4040],
         }
     }
 }
@@ -155,11 +164,6 @@ impl Default for DirectoryBlock {
 }
 
 impl DirectoryBlock {
-    #[allow(unused)]
-    pub(crate) fn is_full(&self) -> bool {
-        self.occupancy[0] == 0xFF && self.occupancy[1] == 0xFF
-    }
-
     pub(crate) fn query(&self, mut index: usize) -> bool {
         if index < 7 {
             // 0-6, first u8
@@ -196,20 +200,12 @@ impl DirectoryBlock {
         }
     }
 
-    // pub(crate) fn allocate(&mut self) -> Option<usize> {
-    //     if self.occupancy[0] != 0xFF {
-    //         let leading_ones = self.occupancy[0].leading_ones();
-    //         self.occupancy[0] |= (1 << (7 - leading_ones)) as u8;
-    //         Some(leading_ones as usize)
-    //     } else if self.occupancy[1] != 0xFF {
-    //         let leading_ones = self.occupancy[1].leading_ones();
-    //         self.occupancy[1] |= (1 << (7 - leading_ones)) as u8;
-    //         Some(7 + leading_ones as usize)
-    //     } else {
-    //         None
-    //     }
-    // }
+    pub(crate) fn reset(&mut self) {
+        self.occupancy[0] = 0x80;
+        self.occupancy[1] = 0x00;
+    }
 
+    #[allow(unused)]
     pub(crate) fn deallocate(&mut self, mut index: usize) {
         if index < 7 {
             index = index + 1;
@@ -269,3 +265,11 @@ impl Default for TripleIndirectBlock {
 }
 
 impl Block for TripleIndirectBlock {}
+
+const_assert_eq!(std::mem::size_of::<SuperBlock>(), 4096);
+const_assert_eq!(std::mem::size_of::<DataBlock>(), 4096);
+const_assert_eq!(std::mem::size_of::<InodeBlock>(), 4096);
+const_assert_eq!(std::mem::size_of::<DirectoryBlock>(), 4096);
+const_assert_eq!(std::mem::size_of::<IndirectBlock>(), 4096);
+const_assert_eq!(std::mem::size_of::<DoubleIndirectBlock>(), 4096);
+const_assert_eq!(std::mem::size_of::<TripleIndirectBlock>(), 4096);
\ No newline at end of file
diff --git a/ayafs-core/src/disk/inode.rs b/ayafs-core/src/disk/inode.rs
index d94b795..eccebd4 100644
--- a/ayafs-core/src/disk/inode.rs
+++ b/ayafs-core/src/disk/inode.rs
@@ -3,7 +3,8 @@ use crate::utils;
 use bitflags::bitflags;
 use fuser::FileType;
 
-pub const DIRECT_NUMBER: usize = 15;
+pub(crate) const DIRECT_NUMBER: usize = 15;
+pub(crate) const INODE_PER_BLOCK: usize = BLOCK_SIZE / INODE_SIZE;
 
 #[derive(Debug, Clone, Copy)]
 pub struct InodeMode(pub u16);
@@ -128,7 +129,7 @@ impl From<InodeMode> for u8 {
 pub struct Inode {
     pub mode: InodeMode,
     pub uid: u32,
-    pub size: u32,
+    pub size: u64,
     pub atime: u32,  // access time, in seconds
     pub ctime: u32,  // change time, in seconds
     pub mtime: u32,  // modify time, in seconds
@@ -141,7 +142,6 @@ pub struct Inode {
     pub single_indirect: u32,
     pub double_indirect: u32,
     pub triple_indirect: u32,
-    pub generation: u32,
     pub file_acl: u32,
     pub dir_acl: u32, // TODO do we have to implement ACL......?
 }
@@ -153,7 +153,6 @@ impl Inode {
         gid: u32,
         time: u32,
         flags: u32,
-        generation: u32,
         file_acl: u32,
         dir_acl: u32,
     ) -> Self {
@@ -173,7 +172,6 @@ impl Inode {
             single_indirect: 0,
             double_indirect: 0,
             triple_indirect: 0,
-            generation,
             file_acl,
             dir_acl,
         }
@@ -187,7 +185,6 @@ impl Inode {
         gid: u32,
         time: u32,
         flags: u32,
-        generation: u32,
         file_acl: u32,
         dir_acl: u32,
     ) -> Self {
@@ -197,7 +194,6 @@ impl Inode {
             gid,
             time,
             flags,
-            generation,
             file_acl,
             dir_acl,
         )
@@ -209,7 +205,6 @@ impl Inode {
         gid: u32,
         time: u32,
         flags: u32,
-        generation: u32,
         file_acl: u32,
         dir_acl: u32,
     ) -> Self {
@@ -219,7 +214,6 @@ impl Inode {
             gid,
             time,
             flags,
-            generation,
             file_acl,
             dir_acl,
         )
@@ -231,7 +225,6 @@ impl Inode {
         gid: u32,
         time: u32,
         flags: u32,
-        generation: u32,
         file_acl: u32,
         dir_acl: u32,
     ) -> Self {
@@ -241,7 +234,6 @@ impl Inode {
             gid,
             time,
             flags,
-            generation,
             file_acl,
             dir_acl,
         )
@@ -253,7 +245,6 @@ impl Inode {
         gid: u32,
         time: u32,
         flags: u32,
-        generation: u32,
         file_acl: u32,
         dir_acl: u32,
     ) -> Self {
@@ -263,7 +254,6 @@ impl Inode {
             gid,
             time,
             flags,
-            generation,
             file_acl,
             dir_acl,
         )
@@ -302,7 +292,6 @@ impl Inode {
             single_indirect: 0,
             double_indirect: 0,
             triple_indirect: 0,
-            generation: 0,
             file_acl: 0,
             dir_acl: 0,
         }
diff --git a/ayafs-core/src/filesystem/trait_impl.rs b/ayafs-core/src/filesystem/trait_impl.rs
index b551cf7..78673ba 100644
--- a/ayafs-core/src/filesystem/trait_impl.rs
+++ b/ayafs-core/src/filesystem/trait_impl.rs
@@ -1,17 +1,14 @@
 use crate::block_device::BLOCK_SIZE;
 use crate::disk::block::DataBlock;
-use crate::disk::inode::InodeMode;
+use crate::disk::inode::{INODE_PER_BLOCK, InodeMode};
 use crate::utils::permissions::{check_access, clear_suid_sgid, get_groups};
 use crate::utils::{from_filetype, from_systime, time_now, to_fileattr, to_filetype};
 use crate::{AyaFS, TTL};
 use fuser::TimeOrNow::{Now, SpecificTime};
-use fuser::{
-    FileType, Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty,
-    ReplyEntry, ReplyOpen, ReplyStatfs, ReplyWrite, ReplyXattr, Request, TimeOrNow,
-};
+use fuser::{FileType, Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, ReplyWrite, Request, TimeOrNow, ReplyStatfs};
 use libc::{
     c_int, EACCES, EBADF, EEXIST, EINVAL, EIO, EISDIR, ENAMETOOLONG, ENOENT, ENOSPC, ENOTDIR,
-    ENOTEMPTY, EPERM, IPOPT_OFFSET, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY, RENAME_EXCHANGE,
+    ENOTEMPTY, EPERM, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY, RENAME_EXCHANGE,
     RENAME_NOREPLACE, R_OK, S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK,
 };
 use log::debug;
@@ -25,13 +22,13 @@ impl AyaFS {}
 
 impl Filesystem for AyaFS {
     fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> Result<(), c_int> {
-        debug!("`init()");
+        debug!("init()");
         Ok(())
     }
 
     fn destroy(&mut self) {
         debug!("destroy()");
-        // TODO 写回
+        self.write_back();
     }
 
     fn lookup(&mut self, req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
@@ -66,8 +63,24 @@ impl Filesystem for AyaFS {
         }
     }
 
+    // fn getxattr(&mut self, _req: &Request<'_>, ino: u64, name: &OsStr, size: u32, reply: ReplyXattr) {
+    //     if let Some(inode) = self.get_inode(ino as usize) {
+    //         debug!(
+    //             "getattr(ino: {}, incoming_uid: {}, inode_uid: {})",
+    //             ino, _req.uid(), inode.uid,
+    //         );
+    //         reply.error(ENOENT);
+    //     } else {
+    //         reply.error(ENOENT);
+    //     }
+    // }
+
     fn getattr(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyAttr) {
         if let Some(inode) = self.get_inode(ino as usize) {
+            debug!(
+                "getattr(ino: {}, incoming_uid: {}, inode_uid: {})",
+                ino, _req.uid(), inode.uid,
+            );
             reply.attr(&TTL, &to_fileattr(ino as usize, inode));
         } else {
             reply.error(ENOENT);
@@ -172,7 +185,7 @@ impl Filesystem for AyaFS {
                     if !write {
                         reply.error(EACCES);
                     } else {
-                        inode.size = size as u32;
+                        inode.size = size;
                         reply.attr(&TTL, &to_fileattr(*inode_index, &inode));
                         self.update_inode(*inode_index, inode);
                     }
@@ -180,7 +193,7 @@ impl Filesystem for AyaFS {
                     if !check_access(req.uid(), req.gid(), inode.uid, inode.gid, inode.mode, W_OK) {
                         reply.error(EACCES);
                     } else {
-                        inode.size = size as u32;
+                        inode.size = size;
                         reply.attr(&TTL, &to_fileattr(ino as usize, &inode));
                     }
                 }
@@ -689,7 +702,7 @@ impl Filesystem for AyaFS {
                 self.create_symlink(0o777, req.uid(), req.gid(), 0)
             {
                 let mut child_inode = child_inode.clone();
-                child_inode.size = target.len() as u32;
+                child_inode.size = target.len() as u64;
                 if target.len() < 60 {
                     debug!("create_symlink: target length < 60, allocating in 'direct' section.");
                     let target_path = target.as_bytes();
@@ -805,7 +818,7 @@ impl Filesystem for AyaFS {
 
             let mut parent_inode = parent_inode.clone();
             match self.lookup_name(parent, &parent_inode, name) {
-                Ok((inode_index, entry_index, inode)) => {
+                Ok((_inode_index, entry_index, _inode)) => {
                     if let Some(new_parent_inode) = self.get_inode(new_parent) {
                         if !check_access(
                             req.uid(),
@@ -825,7 +838,7 @@ impl Filesystem for AyaFS {
 
                         let mut new_parent_inode = new_parent_inode.clone();
                         match self.lookup_name(new_parent, &new_parent_inode, new_name) {
-                            Ok((new_inode_index, new_entry_index, new_inode)) => {
+                            Ok((_new_inode_index, new_entry_index, _new_inode)) => {
                                 // 新文件存在
                                 if flags & RENAME_NOREPLACE != 0 {
                                     // 指定 noreplace 之后不允许覆盖文件
@@ -993,7 +1006,7 @@ impl Filesystem for AyaFS {
             }
             debug!("reading inode {:#x} (offset {} size {})", ino, offset, size);
 
-            if offset as u32 >= inode.size {
+            if offset as u64 >= inode.size {
                 // offset 在 EOF 后面, 直接返回一个 0 长度的空 buffer
                 reply.data(&Vec::new());
                 return;
@@ -1001,10 +1014,12 @@ impl Filesystem for AyaFS {
 
             // let read_length = size.min(inode.size.saturating_sub(offset as u32)) as usize;
             // 这和下面那个是等同的但是不利于让人看懂……
-            let read_length = if offset as u32 + size <= inode.size {
+
+            let size = size as u64;
+            let read_length = if size.checked_add_signed(offset).unwrap() <= inode.size {
                 size // 没有越过 EOF, 读取 size 个 byte
             } else {
-                inode.size - offset as u32 // 越过了 EOF, 读取 inode.size - offset 个 byte
+                inode.size - offset as u64 // 越过了 EOF, 读取 inode.size - offset 个 byte
             } as usize;
 
             let mut read_buffer = vec![0u8; read_length];
@@ -1094,7 +1109,7 @@ impl Filesystem for AyaFS {
                         "writing {} bytes in block {} within inode",
                         write_length_within_block, current_block_index
                     );
-                    (block.block.0[current_offset..current_offset + write_length_within_block])
+                    block.block.0[current_offset..current_offset + write_length_within_block]
                         .copy_from_slice(&data[write_ptr..write_ptr + write_length_within_block]);
                     write_ptr += write_length_within_block;
                 } else {
@@ -1107,7 +1122,7 @@ impl Filesystem for AyaFS {
                         let block = self
                             .access_block_mut::<DataBlock>(&inode, block_index_within_inode)
                             .unwrap();
-                        (block.block.0[current_offset..current_offset + write_length_within_block])
+                        block.block.0[current_offset..current_offset + write_length_within_block]
                             .copy_from_slice(
                                 &data[write_ptr..write_ptr + write_length_within_block],
                             );
@@ -1119,7 +1134,7 @@ impl Filesystem for AyaFS {
                 }
             }
 
-            inode.size = inode.size.max(offset as u32 + write_length as u32);
+            inode.size = inode.size.max(offset as u64 + write_length as u64);
             self.update_inode(ino as usize, inode);
             reply.written(write_length as u32);
         } else {
@@ -1127,30 +1142,6 @@ impl Filesystem for AyaFS {
         }
     }
 
-    // fn getxattr(
-    //     &mut self,
-    //     _req: &Request<'_>,
-    //     ino: u64,
-    //     name: &OsStr,
-    //     size: u32,
-    //     reply: ReplyXattr,
-    // ) {
-    //     todo!()
-    // }
-    //
-    // fn setxattr(
-    //     &mut self,
-    //     _req: &Request<'_>,
-    //     ino: u64,
-    //     name: &OsStr,
-    //     _value: &[u8],
-    //     flags: i32,
-    //     position: u32,
-    //     reply: ReplyEmpty,
-    // ) {
-    //     todo!()
-    // }
-
     fn release(
         &mut self,
         _req: &Request<'_>,
@@ -1284,9 +1275,25 @@ impl Filesystem for AyaFS {
         }
     }
 
-    // fn statfs(&mut self, _req: &Request<'_>, _ino: u64, reply: ReplyStatfs) {
-    //     todo!()
-    // }
+    fn statfs(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyStatfs) {
+        if let Some(_) = self.get_inode(ino as usize) {
+            self.super_block.used_inode_number = self.inode_bitmap.count;
+            self.super_block.used_block_number = self.data_bitmap.count;
+
+            reply.statfs(
+                self.super_block.used_block_number,
+                self.super_block.data_block_number - self.super_block.used_block_number,
+                self.super_block.data_block_number - self.super_block.used_block_number,
+                self.super_block.used_inode_number,
+                self.super_block.inode_block_number * INODE_PER_BLOCK as u64 - self.super_block.used_inode_number,
+                BLOCK_SIZE as u32,
+                255,
+                BLOCK_SIZE as u32,
+            );
+        } else {
+            reply.error(ENOENT);
+        }
+    }
 
     fn access(&mut self, req: &Request<'_>, ino: u64, mask: i32, reply: ReplyEmpty) {
         // mask:
@@ -1295,6 +1302,7 @@ impl Filesystem for AyaFS {
         debug!("Filesystem::access(ino: {}, mask: {})", ino, mask);
 
         if let Some(inode) = self.get_inode(ino as usize) {
+            debug!("  uid: {}, gid: {}, incoming_uid: {}, incoming_gid: {}, mask: {}", inode.uid, inode.gid, req.uid(), req.gid(), mask);
             if mask == libc::F_OK // 只要检查是否存在
                 || check_access(req.uid(), req.gid(), inode.uid, inode.gid, inode.mode, mask)
             // 需要检查 rwx 权限
diff --git a/ayafs-core/src/lib.rs b/ayafs-core/src/lib.rs
index 5ec118a..db3ac28 100644
--- a/ayafs-core/src/lib.rs
+++ b/ayafs-core/src/lib.rs
@@ -1,3 +1,6 @@
+#[macro_use]
+extern crate static_assertions;
+
 pub mod block_device;
 pub mod disk;
 pub mod filesystem;
@@ -15,17 +18,17 @@ use std::num::NonZeroUsize;
 use std::sync::atomic::AtomicU64;
 use std::sync::Arc;
 use std::time::Duration;
+use libc::{gid_t, uid_t};
 
 use crate::disk::block::{DirectoryEntry, InodeBlock, SuperBlock};
 use crate::memory::cached_block::BlockCache;
 use block_device::{BlockDevice, BLOCK_SIZE};
 use disk::bitmap::Bitmap;
 use disk::block::DataBlock;
-use disk::inode::INODE_SIZE;
-use users::{get_current_gid, get_current_uid};
+use crate::disk::inode::INODE_PER_BLOCK;
+
 
 const TTL: Duration = Duration::new(0, 0);
-const INODE_PER_BLOCK: usize = BLOCK_SIZE / INODE_SIZE;
 
 /// The design of MyFS is rather simple:
 /// +-------------------+
@@ -69,7 +72,7 @@ pub struct AyaFS {
 }
 
 impl AyaFS {
-    pub fn new(device: Arc<dyn BlockDevice>, total_block_number: usize) -> Self {
+    pub fn new(device: Arc<dyn BlockDevice>, total_block_number: usize, uid: uid_t, gid: gid_t) -> Self {
         let max_inode_number: usize = 16384; // TODO: remove hard-coded magic number
         let inode_block_number = max_inode_number / INODE_PER_BLOCK; // == 128
         let inode_bitmap_block_number = (inode_block_number + BLOCK_SIZE - 1) / BLOCK_SIZE;
@@ -101,40 +104,135 @@ impl AyaFS {
             inode_bitmap_block_number,
             inode_block_number,
             data_block_number,
+            total_block_number,
+            0,
+            0
         );
 
-        let mut data_bitmap = Bitmap::new(1, data_bitmap_block_number, device.clone());
+        let mut data_bitmap = Bitmap::new(1, data_bitmap_block_number, device.clone(), 0);
         let _ = data_bitmap.allocate().unwrap(); // data block 0 is not usable
         let mut inode_bitmap = Bitmap::new(
             data_bitmap_block_number + 1,
             inode_bitmap_block_number,
             device.clone(),
+            0,
         );
         let _ = inode_bitmap.allocate().unwrap(); // inode block 0 is not usable
 
+        let inode_start_block = data_bitmap_block_number + inode_bitmap_block_number + 1;
+        let data_start_block = inode_start_block + inode_block_number;
+
         let mut fs = Self {
             device: device.clone(),
             data_bitmap,
             inode_bitmap,
-            inode_start_block: data_bitmap_block_number + inode_bitmap_block_number + 1,
-            data_start_block: data_bitmap_block_number
-                + inode_bitmap_block_number
-                + inode_block_number
-                + 1,
+            inode_start_block,
+            data_start_block,
 
             next_file_handle: AtomicU64::new(3), // 0,1,2 are stdin, stdout and stderr
             file_handle_map: HashMap::new(),
 
             dir_entry_map: LruCache::new(NonZeroUsize::new(1024).unwrap()),
 
-            cached_inodes: BlockCache::new(device.clone(), 1024),
-            cached_blocks: BlockCache::new(device.clone(), 8192),
+            cached_inodes: BlockCache::new(device.clone(), 8192, inode_start_block),
+            cached_blocks: BlockCache::new(device.clone(), 16384, data_start_block),
 
             super_block,
         };
 
-        fs.create_directory(0o755, get_current_uid(), get_current_gid(), 0, None);
+        fs.create_directory(0o755, uid, gid, 0, None);
 
         fs
     }
+
+    pub fn load(device: Arc<dyn BlockDevice>) -> Self {
+        let mut buffer = [0u8; 4096];
+        device.read(0, &mut buffer);
+
+        let super_block: SuperBlock = unsafe {
+            std::mem::transmute_copy(&buffer)
+        };
+        let data_bitmap_block_number = super_block.data_bitmap_block_number as usize;
+        let inode_bitmap_block_number = super_block.inode_bitmap_block_number as usize;
+        let inode_block_number = super_block.inode_block_number as usize;
+        let data_block_number = super_block.data_block_number as usize;
+        debug!("data_bitmap_block_number: {}", data_bitmap_block_number);
+        debug!("inode_bitmap_block_number: {}", inode_bitmap_block_number);
+        debug!("inode_block_number:  {}", inode_block_number);
+        debug!("data_block_number:  {}", data_block_number);
+        debug!("total_block_number: {}", super_block.total_block_number);
+        debug!(
+            "sum:  {}",
+            1 + data_bitmap_block_number
+                + inode_bitmap_block_number
+                + inode_block_number
+                + data_block_number
+        );
+
+        let data_bitmap = Bitmap::load(
+            1,
+            data_bitmap_block_number,
+            device.clone(),
+            super_block.used_block_number,
+        );
+        debug!("data_bitmap starting from: {:?}", data_bitmap.peek());
+
+        let inode_bitmap = Bitmap::load(
+            data_bitmap_block_number + 1,
+            inode_bitmap_block_number,
+            device.clone(),
+            super_block.used_inode_number,
+        );
+        debug!("inode_bitmap starting from: {:?}", inode_bitmap.peek());
+
+        let inode_start_block = data_bitmap_block_number + inode_bitmap_block_number + 1;
+        let data_start_block = inode_start_block + inode_block_number;
+
+        Self {
+            device: device.clone(),
+            data_bitmap,
+            inode_bitmap,
+            inode_start_block,
+            data_start_block,
+
+            next_file_handle: AtomicU64::new(3), // 0,1,2 are stdin, stdout and stderr
+            file_handle_map: HashMap::new(),
+
+            dir_entry_map: LruCache::new(NonZeroUsize::new(1024).unwrap()),
+
+            cached_inodes: BlockCache::new(device.clone(), 1024, inode_start_block),
+            cached_blocks: BlockCache::new(device.clone(), 8192, data_start_block),
+
+            super_block,
+        }
+    }
+
+    pub fn write_back(&mut self) {
+        self.super_block.used_inode_number = self.inode_bitmap.count;
+        self.super_block.used_block_number = self.data_bitmap.count;
+        let super_block_buffer = unsafe {
+            let ptr = &self.super_block as *const SuperBlock as *const u8;
+            std::slice::from_raw_parts(ptr, std::mem::size_of::<SuperBlock>())
+        };
+        self.device.write(0, super_block_buffer);
+
+        while let Some((inode_index, dir_entry_map)) = self.dir_entry_map.pop_lru() {
+            debug!("writing back direntry map for inode {}", inode_index);
+            let mut inode = self.get_inode(inode_index).unwrap().clone();
+            self.write_back_direntry(
+                inode_index,
+                &mut inode,
+                dir_entry_map,
+            ).unwrap();
+            self.update_inode(inode_index, inode);
+        } // dir entry 的 write back 是写回到 block / inode cache 里, 所以要在前面
+
+        debug!("data_bitmap stopping at: {:?}", self.data_bitmap.peek());
+        debug!("inode_bitmap stopping at: {:?}", self.inode_bitmap.peek());
+        self.data_bitmap.write_back();
+        self.inode_bitmap.write_back();
+
+        self.cached_blocks.write_back();
+        self.cached_inodes.write_back();
+    }
 }
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;
diff --git a/ayafs-core/src/tests/common/mod.rs b/ayafs-core/src/tests/common/mod.rs
index 3abfcb4..134c84a 100644
--- a/ayafs-core/src/tests/common/mod.rs
+++ b/ayafs-core/src/tests/common/mod.rs
@@ -1,9 +1,10 @@
 use crate::block_device::memory_disk::MemoryDisk;
 use crate::AyaFS;
 use std::sync::Arc;
+use users::{get_current_gid, get_current_uid};
 
 #[allow(unused)]
 pub(crate) fn setup() -> AyaFS {
     let mem_disk = Arc::new(MemoryDisk::new(1059715));
-    AyaFS::new(mem_disk, 1059715)
+    AyaFS::new(mem_disk, 1059715, get_current_uid(), get_current_gid())
 }
diff --git a/ayafs-core/src/tests/mod.rs b/ayafs-core/src/tests/mod.rs
index df442c1..98984ff 100644
--- a/ayafs-core/src/tests/mod.rs
+++ b/ayafs-core/src/tests/mod.rs
@@ -1,6 +1,5 @@
 #[cfg(test)]
 mod bitmap;
 mod common;
-
 #[cfg(test)]
 mod block_cache;
diff --git a/ayafs-core/src/utils/constants.rs b/ayafs-core/src/utils/constants.rs
deleted file mode 100644
index 8b13789..0000000
--- a/ayafs-core/src/utils/constants.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/ayafs-core/src/utils/mod.rs b/ayafs-core/src/utils/mod.rs
index 468ebdb..d73cb3e 100644
--- a/ayafs-core/src/utils/mod.rs
+++ b/ayafs-core/src/utils/mod.rs
@@ -1,4 +1,3 @@
-mod constants;
 pub mod permissions;
 
 use crate::block_device::BLOCK_SIZE;
@@ -7,6 +6,8 @@ use crate::{AyaFS, INODE_PER_BLOCK};
 use fuser::{FileAttr, FileType};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
 
+// pub(crate) const ANON_INODE_FS_MAGIC: libc::__fsword_t = 0x09041934;
+
 pub(crate) fn time_now() -> u32 {
     SystemTime::now()
         .duration_since(UNIX_EPOCH)
@@ -25,16 +26,6 @@ pub(crate) fn to_systime(time: u32) -> SystemTime {
     UNIX_EPOCH + Duration::from_secs(time as u64)
 }
 
-// File type code, one of:
-// 0x0 	Unknown.
-// 0x1 	Regular file.
-// 0x2 	Directory.
-// 0x3 	Character device file.
-// 0x4 	Block device file.
-// 0x5 	FIFO.
-// 0x6 	Socket.
-// 0x7 	Symbolic link.
-
 pub(crate) fn from_filetype(file_type: FileType) -> u8 {
     match file_type {
         FileType::NamedPipe => 0x5,
@@ -85,7 +76,7 @@ impl AyaFS {
     /// 输入 inode 编号, 返回它对应的 block number 和 block 内 offset
     pub(crate) fn locate_inode(&self, inode_index: usize) -> (usize, usize) {
         let block_number =
-            inode_index / INODE_PER_BLOCK + 1 + self.inode_bitmap.length + self.data_bitmap.length;
+            inode_index / INODE_PER_BLOCK; // + 1 + self.inode_bitmap.length + self.data_bitmap.length;
         let block_offset = inode_index % INODE_PER_BLOCK * INODE_SIZE;
         (block_number, block_offset)
     }
-- 
cgit v1.2.3-70-g09d2