summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/disk/allocation.rs16
-rw-r--r--src/disk/inode.rs71
-rw-r--r--src/filesystem/trait_impl.rs271
-rw-r--r--src/main.rs7
-rw-r--r--src/memory/cached_block.rs16
-rw-r--r--src/memory/cached_inode.rs10
-rw-r--r--src/tests/block_cache.rs117
-rw-r--r--src/utils/mod.rs49
8 files changed, 425 insertions, 132 deletions
diff --git a/src/disk/allocation.rs b/src/disk/allocation.rs
index bfdba46..5643dd3 100644
--- a/src/disk/allocation.rs
+++ b/src/disk/allocation.rs
@@ -194,11 +194,8 @@ impl AyaFS {
{
let mut triple_indirect_block = triple_indirect_block.clone();
let mut block_modified = false;
- for double_indirect_entry in triple_indirect_block
- .block
- .double_indirect
- .iter_mut()
- .rev()
+ for double_indirect_entry in
+ triple_indirect_block.block.double_indirect.iter_mut().rev()
{
// 如果这个位置的 double indirect 存在
if self.data_bitmap.query(*double_indirect_entry as usize) {
@@ -212,8 +209,10 @@ impl AyaFS {
return Some(block_index); // 成功则直接返回
} else {
// 失败则把这个 double indirect 销毁
- let double_indirect_entry_to_deallocate = std::mem::replace(double_indirect_entry, 0);
- self.data_bitmap.deallocate(double_indirect_entry_to_deallocate as usize);
+ let double_indirect_entry_to_deallocate =
+ std::mem::replace(double_indirect_entry, 0);
+ self.data_bitmap
+ .deallocate(double_indirect_entry_to_deallocate as usize);
triple_indirect_block.dirty = true;
block_modified = true;
}
@@ -246,7 +245,8 @@ impl AyaFS {
} else {
// 失败则把这个 indirect 销毁
let indirect_entry_to_deallocate = std::mem::replace(indirect_entry, 0);
- self.data_bitmap.deallocate(indirect_entry_to_deallocate as usize);
+ self.data_bitmap
+ .deallocate(indirect_entry_to_deallocate as usize);
double_indirect_block.dirty = true;
block_modified = true;
}
diff --git a/src/disk/inode.rs b/src/disk/inode.rs
index 48085d8..1095aca 100644
--- a/src/disk/inode.rs
+++ b/src/disk/inode.rs
@@ -1,4 +1,6 @@
use bitflags::bitflags;
+use fuser::{FileAttr, FileType};
+use std::fs::File;
const DIRECT_NUMBER: usize = 15;
@@ -30,6 +32,43 @@ bitflags! {
}
}
+impl InodeMode {
+ pub(crate) fn perm(&self) -> u16 {
+ self.0 & 0x0FFF
+ }
+
+ pub(crate) fn is_file(&self) -> bool {
+ (self.0 & 0xF000) == Self::IFREG.0
+ }
+
+ pub(crate) fn is_dir(&self) -> bool {
+ (self.0 & 0xF000) == Self::IFDIR.0
+ }
+
+ pub(crate) fn validate(mode_value: u16) -> Option<Self> {
+ let valid_flags: [u16; 7] = [0x1000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000];
+ valid_flags
+ .contains(&(mode_value & 0xF000))
+ .then(|| Self(mode_value))
+ }
+}
+
+impl From<InodeMode> for FileType {
+ fn from(value: InodeMode) -> Self {
+ let type_flag = value.0 & 0xF000;
+ match type_flag {
+ 0x1000 => FileType::NamedPipe,
+ 0x2000 => FileType::CharDevice,
+ 0x4000 => FileType::Directory,
+ 0x6000 => FileType::BlockDevice,
+ 0x8000 => FileType::RegularFile,
+ 0xA000 => FileType::Symlink,
+ 0xC000 => FileType::Socket,
+ _ => panic!("Invalid inode mode {:x}", type_flag),
+ }
+ }
+}
+
/// Pretty much the same with ext2, with minor changes:
/// - removed OS dependent attributes (osd1 & osd2)
/// - removed i_faddr since fragmentation is not supported
@@ -39,24 +78,24 @@ bitflags! {
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Inode {
- mode: InodeMode,
- uid: u32,
- size: u32,
- atime: u32, // access time, in seconds
- ctime: u32, // change time, in seconds
- mtime: u32, // modify time, in seconds
- crtime: u32, // create time, in seconds
- gid: u32,
+ pub mode: InodeMode,
+ pub uid: u32,
+ pub size: u32,
+ pub atime: u32, // access time, in seconds
+ pub ctime: u32, // change time, in seconds
+ pub mtime: u32, // modify time, in seconds
+ pub crtime: u32, // create time, in seconds
+ pub gid: u32,
pub n_links: u16,
pub n_blocks: u32,
- flags: u32, // TODO: do we actually need this? maybe just return 0
+ pub flags: u32, // TODO: do we actually need this? maybe just return 0
pub direct: [u32; DIRECT_NUMBER],
pub single_indirect: u32,
pub double_indirect: u32,
pub triple_indirect: u32,
- generation: u32,
- file_acl: u32,
- dir_acl: u32, // TODO do we have to implement ACL......?
+ pub generation: u32,
+ pub file_acl: u32,
+ pub dir_acl: u32, // TODO do we have to implement ACL......?
}
impl Inode {
@@ -159,6 +198,14 @@ impl Inode {
)
}
+ pub(crate) fn is_file(&self) -> bool {
+ self.mode.is_file()
+ }
+
+ pub(crate) fn is_dir(&self) -> bool {
+ self.mode.is_dir()
+ }
+
pub fn empty() -> Self {
Self::new(InodeMode(0), 0, 0, 0, 0, 0, 0, 0)
}
diff --git a/src/filesystem/trait_impl.rs b/src/filesystem/trait_impl.rs
index 3a60578..a25a383 100644
--- a/src/filesystem/trait_impl.rs
+++ b/src/filesystem/trait_impl.rs
@@ -1,12 +1,17 @@
-use crate::AyaFS;
+use crate::block_device::BLOCK_SIZE;
+use crate::disk::inode::InodeMode;
+use crate::utils::make_fileattr;
+use crate::{utils, AyaFS, TTL};
use fuser::{
- Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry,
- ReplyLseek, ReplyWrite, Request, TimeOrNow,
+ FileAttr, FileType, Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty,
+ ReplyEntry, ReplyLseek, ReplyWrite, Request, TimeOrNow,
};
-use libc::{c_int, ENOENT, ENOSPC, ENOSYS};
+use libc::{c_int, ENAMETOOLONG, ENOENT, ENOSPC, ENOSYS, ENOTDIR};
use log::debug;
use std::ffi::OsStr;
+use std::os::unix::ffi::OsStrExt;
use std::time::SystemTime;
+use users::{get_current_gid, get_current_uid};
impl Filesystem for AyaFS {
fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> Result<(), c_int> {
@@ -19,11 +24,6 @@ impl Filesystem for AyaFS {
}
fn lookup(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEntry) {
- debug!(
- "Filesystem::lookup called with parent {} name {}",
- parent,
- name.to_str().unwrap()
- );
let parent = parent as usize;
if let Some(inode) = self.get_inode(parent) {
// debug!("{:?}", inode);
@@ -43,11 +43,28 @@ impl Filesystem for AyaFS {
fn getattr(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyAttr) {
debug!("Filesystem::getattr(ino: {})", ino);
- let ino = ino as usize;
- if let Some(inode) = self.get_inode(ino) {
- // debug!("{:?}", inode);
+ if let Some(inode) = self.get_inode(ino as usize) {
+ let attr = FileAttr {
+ ino,
+ size: inode.size as u64,
+ blocks: inode.n_blocks as u64,
+ atime: utils::to_systime(inode.atime),
+ mtime: utils::to_systime(inode.mtime),
+ ctime: utils::to_systime(inode.ctime),
+ crtime: utils::to_systime(inode.crtime),
+ kind: inode.mode.into(),
+ perm: inode.mode.perm(),
+ nlink: inode.n_links as u32,
+ uid: inode.uid,
+ gid: inode.gid,
+ rdev: 0,
+ blksize: BLOCK_SIZE as u32,
+ flags: inode.flags,
+ };
+ reply.attr(&TTL, &attr);
+ } else {
+ reply.error(ENOENT);
}
- reply.error(ENOENT);
}
fn setattr(
@@ -57,23 +74,92 @@ impl Filesystem for AyaFS {
mode: Option<u32>,
uid: Option<u32>,
gid: Option<u32>,
- size: Option<u64>,
- _atime: Option<TimeOrNow>,
- _mtime: Option<TimeOrNow>,
- _ctime: Option<SystemTime>,
+ size: Option<u64>, // TODO 为什么 setattr 还可以设置 size??
+ atime: Option<TimeOrNow>,
+ mtime: Option<TimeOrNow>,
+ ctime: Option<SystemTime>,
fh: Option<u64>,
- _crtime: Option<SystemTime>,
+ crtime: Option<SystemTime>,
_chgtime: Option<SystemTime>,
_bkuptime: Option<SystemTime>,
flags: Option<u32>,
reply: ReplyAttr,
) {
- debug!(
- "Filesystem::setattr(ino: {:#x?}, mode: {:?}, uid: {:?}, \
- gid: {:?}, size: {:?}, fh: {:?}, flags: {:?})",
- ino, mode, uid, gid, size, fh, flags
- );
- reply.error(ENOSYS);
+ if let Some(inode) = self.get_inode_mut(ino as usize) {
+ let mode = mode
+ .and_then(|mode_value| {
+ InodeMode::validate(mode_value as u16) // high 16 bit truncated
+ })
+ .unwrap_or(inode.mode);
+ inode.mode = mode;
+ // 如果传入的 InodeMode 是合法结果, 那么得到 Some(mode), 否则 None
+ // 需要检查权限吗? 如果需要, 如何知道 invoke 这个 callback 的 UID/GID?
+
+ let size = size.unwrap_or(inode.size as u64);
+ inode.size = size as u32;
+ // TODO 为什么可以设置 size 呢……
+
+ let uid = uid.unwrap_or(inode.uid);
+ let gid = gid.unwrap_or(inode.gid);
+ inode.uid = uid;
+ inode.gid = gid;
+
+ let (atime, atime_inner) = atime
+ .map(|atime| {
+ let system_time = match atime {
+ TimeOrNow::SpecificTime(system_time) => system_time,
+ TimeOrNow::Now => SystemTime::now(),
+ };
+ (system_time, utils::from_systime(system_time))
+ })
+ .unwrap_or((utils::to_systime(inode.atime), inode.atime));
+ inode.atime = atime_inner;
+
+ let (mtime, mtime_inner) = mtime
+ .map(|mtime| {
+ let system_time = match mtime {
+ TimeOrNow::SpecificTime(system_time) => system_time,
+ TimeOrNow::Now => SystemTime::now(),
+ };
+ (system_time, utils::from_systime(system_time))
+ })
+ .unwrap_or((utils::to_systime(inode.mtime), inode.mtime));
+ inode.mtime = mtime_inner;
+
+ let (ctime, ctime_inner) = ctime
+ .map(|ctime| (ctime, utils::from_systime(ctime)))
+ .unwrap_or((utils::to_systime(inode.ctime), inode.ctime));
+ inode.ctime = ctime_inner;
+
+ let (crtime, crtime_inner) = crtime
+ .map(|crtime| (crtime, utils::from_systime(crtime)))
+ .unwrap_or((utils::to_systime(inode.crtime), inode.crtime));
+ inode.crtime = crtime_inner;
+
+ let flags = flags.unwrap_or(inode.flags);
+ inode.flags = flags;
+
+ let attr = FileAttr {
+ ino,
+ size,
+ blocks: inode.n_blocks as u64,
+ atime,
+ mtime,
+ ctime,
+ crtime,
+ kind: mode.into(),
+ perm: mode.perm(),
+ nlink: inode.n_links as u32,
+ uid,
+ gid,
+ rdev: 0,
+ blksize: BLOCK_SIZE as u32,
+ flags,
+ };
+ reply.attr(&TTL, &attr);
+ } else {
+ reply.error(ENOSYS);
+ }
}
fn readlink(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyData) {
@@ -87,15 +173,46 @@ impl Filesystem for AyaFS {
parent: u64,
name: &OsStr,
mode: u32,
- umask: u32,
- rdev: u32,
+ _umask: u32, // umask 是用不到的
+ _rdev: u32, // the device number (only valid if created file is a device)
reply: ReplyEntry,
) {
debug!(
- "Filesystem::mknod(parent: {}, name: {:?}, mode: {}, umask: {}, rdev: {})",
- parent, name, mode, umask, rdev
+ "Filesystem::mknod(parent: {}, name: {:?}, mode: {}, umask: {})",
+ parent, name, mode, _umask
);
- reply.error(ENOSPC);
+ if let Some(inode) = self.get_inode(parent as usize) {
+ if inode.is_dir() {
+ let name = name.as_bytes();
+ if name.len() <= 255 {
+ let permissions = (mode & 0o777) as u16;
+ if let Some(inode_index) = self.create_inode(
+ permissions,
+ InodeMode::IFREG,
+ get_current_uid(),
+ get_current_gid(),
+ 0,
+ ) {
+ let inode = self.get_inode(inode_index).unwrap();
+ let file_attr = make_fileattr(inode_index, inode);
+ // TODO 把 inode 挂到 parent 下
+ reply.entry(&TTL, &file_attr, 0);
+ } else {
+ // create_inode 失败 -> no enough space
+ reply.error(ENOSPC);
+ }
+ } else {
+ // name 长度超过 255 -> File name too long
+ reply.error(ENAMETOOLONG);
+ }
+ } else {
+ // parent 不是 IFDIR -> Not a directory
+ reply.error(ENOTDIR);
+ }
+ } else {
+ // parent 不存在 -> No such file or directory
+ reply.error(ENOENT);
+ }
}
fn mkdir(
@@ -104,18 +221,54 @@ impl Filesystem for AyaFS {
parent: u64,
name: &OsStr,
mode: u32,
- umask: u32,
+ _umask: u32, // umask 应该也是用不到的
reply: ReplyEntry,
) {
+ if let Some(inode) = self.get_inode(parent as usize) {
+ if inode.is_dir() {
+ let name = name.as_bytes();
+ if name.len() <= 255 {
+ let permissions = (mode & 0o777) as u16;
+ if let Some(inode_index) = self.create_inode(
+ permissions,
+ InodeMode::IFDIR,
+ get_current_uid(),
+ get_current_gid(),
+ 0,
+ ) {
+ let inode = self.get_inode(inode_index).unwrap();
+ let file_attr = make_fileattr(inode_index, inode);
+ // TODO 把 inode 挂到 parent 下
+ reply.entry(&TTL, &file_attr, 0);
+ } else {
+ // create_inode 失败 -> no enough space
+ reply.error(ENOSPC);
+ }
+ } else {
+ // name 长度超过 255 -> File name too long
+ reply.error(ENAMETOOLONG);
+ }
+ } else {
+ // parent 不是 IFDIR -> Not a directory
+ reply.error(ENOTDIR);
+ }
+ } else {
+ // parent 不存在 -> No such file or directory
+ reply.error(ENOENT);
+ }
+ }
+
+ fn unlink(&mut self, _req: &Request<'_>, parent: u64, name: &OsStr, reply: ReplyEmpty) {
debug!(
- "Filesystem::mkdir(parent: {}, name: {:?}, mode: {}, umask: {})",
- parent, name, mode, umask
+ "unlink(parent: {:#x?}, name: {:?})",
+ parent, name,
);
- if let Some(inode) = self.get_inode(parent as usize) {
+ if let Some(inode) = self.get_inode_mut(parent as usize) {
+ // TODO 找到这个 inode 并且删掉
+ reply.ok();
} else {
reply.error(ENOENT);
}
- // reply.error(ENOSPC);
}
fn read(
@@ -140,7 +293,29 @@ impl Filesystem for AyaFS {
offset: i64,
mut reply: ReplyDirectory,
) {
- todo!()
+ if let Some(inode) = self.get_inode(ino as usize) {
+ } else {
+ reply.error(ENOENT);
+ }
+
+ // if ino != 1 {
+ // reply.error(ENOENT);
+ // return;
+ // }
+ //
+ // let entries = vec![
+ // (1, FileType::Directory, "."),
+ // (1, FileType::Directory, ".."),
+ // (2, FileType::RegularFile, "hello.txt"),
+ // ];
+ //
+ // for (i, entry) in entries.into_iter().enumerate().skip(offset as usize) {
+ // // i + 1 means the index of the next entry
+ // if reply.add(entry.0, (i + 1) as i64, entry.1, entry.2) {
+ // break;
+ // }
+ // }
+ // reply.ok();
}
fn access(&mut self, _req: &Request<'_>, ino: u64, mask: i32, reply: ReplyEmpty) {
@@ -161,32 +336,6 @@ impl Filesystem for AyaFS {
whence: i32,
reply: ReplyLseek,
) {
- debug!(
- "lseek(ino: {:#x?}, fh: {}, offset: {}, whence: {})",
- ino, fh, offset, whence
- );
- reply.error(ENOSYS);
- }
-
- fn copy_file_range(
- &mut self,
- _req: &Request<'_>,
- ino_in: u64,
- fh_in: u64,
- offset_in: i64,
- ino_out: u64,
- fh_out: u64,
- offset_out: i64,
- len: u64,
- flags: u32,
- reply: ReplyWrite,
- ) {
- debug!(
- "copy_file_range(ino_in: {:#x?}, fh_in: {}, \
- offset_in: {}, ino_out: {:#x?}, fh_out: {}, offset_out: {}, \
- len: {}, flags: {})",
- ino_in, fh_in, offset_in, ino_out, fh_out, offset_out, len, flags
- );
reply.error(ENOSYS);
}
}
diff --git a/src/main.rs b/src/main.rs
index a5ec616..2df0a10 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,8 +8,6 @@ mod utils;
use clap::Parser;
use fuser::MountOption;
use log::debug;
-use lru::LruCache;
-use std::num::NonZeroUsize;
use std::sync::Arc;
use std::time::Duration;
@@ -20,7 +18,6 @@ use block_device::{memory_disk::MemoryDisk, BlockDevice, BLOCK_SIZE};
use disk::bitmap::Bitmap;
use disk::block::DataBlock;
use disk::inode::INODE_SIZE;
-use memory::cached_block::CachedBlock;
use users::{get_current_gid, get_current_uid};
#[derive(Parser, Debug)]
@@ -66,8 +63,6 @@ struct AyaFS {
cached_inodes: BlockCache<InodeBlock>,
cached_blocks: BlockCache<DataBlock>,
- // cached_inodes: LruCache<usize, CachedBlock<InodeBlock>>,
- // cached_blocks: LruCache<usize, CachedBlock<DataBlock>>,
}
impl AyaFS {
@@ -118,8 +113,6 @@ impl AyaFS {
+ 1,
cached_inodes: BlockCache::new(device.clone(), 256),
cached_blocks: BlockCache::new(device.clone(), 256),
- // cached_inodes: LruCache::new(NonZeroUsize::new(256).unwrap()),
- // cached_blocks: LruCache::new(NonZeroUsize::new(256).unwrap()),
};
fs.create_inode(
diff --git a/src/memory/cached_block.rs b/src/memory/cached_block.rs
index 9e266ef..eb59a4b 100644
--- a/src/memory/cached_block.rs
+++ b/src/memory/cached_block.rs
@@ -2,6 +2,7 @@ use crate::block_device::{BlockDevice, BLOCK_SIZE};
use crate::disk::block::Block;
use crate::AyaFS;
use and_then_some::BoolExt;
+use log::debug;
use lru::LruCache;
use std::num::NonZeroUsize;
use std::sync::Arc;
@@ -46,11 +47,9 @@ impl<T: Block> BlockCache<T> {
pub(crate) fn load_block(&mut self, index: usize) -> bool {
if self.cache.contains(&index) == false {
- let block = T::default();
- let buffer = unsafe {
- std::slice::from_raw_parts_mut(&block as *const T as *mut u8, BLOCK_SIZE)
- };
- self.device.read(index, buffer);
+ let mut buffer = [0u8; BLOCK_SIZE];
+ self.device.read(index, &mut buffer);
+ let block: T = unsafe { std::mem::transmute_copy(&buffer) };
let cached_block = CachedBlock {
block,
index,
@@ -77,8 +76,11 @@ impl<T: Block> BlockCache<T> {
/// 从 LRU cache 里获取一个 block 的可变引用, 如果没有在 cache 中会加载.
pub(crate) fn get_block_mut<U: Block>(&mut self, index: usize) -> Option<&mut CachedBlock<U>> {
- self.load_block(index)
- .and_then(|| self.cache.get_mut(&index).map(convert_mut::<T, U>))
+ debug!("Blockcache get block mut");
+ self.load_block(index).and_then(|| {
+ debug!("block loaded");
+ self.cache.get_mut(&index).map(convert_mut::<T, U>)
+ })
}
/// 从 LRU cache 中读取一个 block 的引用, *不会* 影响 LRU cache 的结构, 如果没有在 cache 中不会加载.
diff --git a/src/memory/cached_inode.rs b/src/memory/cached_inode.rs
index b81bd2e..dd5e5c3 100644
--- a/src/memory/cached_inode.rs
+++ b/src/memory/cached_inode.rs
@@ -1,7 +1,8 @@
-use crate::disk::block::{Block, InodeBlock};
+use crate::disk::block::InodeBlock;
use crate::disk::inode::{Inode, InodeMode, INODE_SIZE};
-use crate::AyaFS;
+use crate::{utils, AyaFS};
use and_then_some::BoolExt;
+use log::debug;
impl AyaFS {
pub(crate) fn create_inode(
@@ -12,20 +13,23 @@ impl AyaFS {
gid: u32,
flags: u32,
) -> Option<usize> {
+ debug!("create inode");
self.inode_bitmap.allocate().map(|inode_index| {
+ debug!("creating inode");
self.get_inode_mut(inode_index).map(|inode| {
*inode = Inode::make_inode(
permissions,
mode,
uid,
gid,
- Self::time_now(),
+ utils::time_now(),
flags,
0,
0,
0,
);
});
+ debug!("inode created");
inode_index
})
}
diff --git a/src/tests/block_cache.rs b/src/tests/block_cache.rs
index bbea3a0..90875ae 100644
--- a/src/tests/block_cache.rs
+++ b/src/tests/block_cache.rs
@@ -62,7 +62,10 @@ fn test_inode_allocation() {
}
let double_indirect = inode.double_indirect;
- println!("double indirect is {} after allocation", inode.double_indirect);
+ println!(
+ "double indirect is {} after allocation",
+ inode.double_indirect
+ );
fs.update_inode(inode_index, inode);
@@ -96,7 +99,10 @@ fn test_inode_deallocation() {
assert!(fs.data_bitmap.query(inode.double_indirect as usize));
for i in 0..INDIRECT_NUMBER + 5 {
- println!("Deallocated {}", fs.deallocate_block_for(&mut inode).unwrap());
+ println!(
+ "Deallocated {}",
+ fs.deallocate_block_for(&mut inode).unwrap()
+ );
}
println!("single indirect is {}", inode.single_indirect);
@@ -121,57 +127,116 @@ fn test_multiple_inode_allocation() {
const DIRECT_NUMBER: u32 = 15;
const INDIRECT_NUMBER: u32 = 1024;
- for i in 0 .. DIRECT_NUMBER + INDIRECT_NUMBER {
- println!("Allcoated {} in inode {}", fs.allocate_block_for(&mut inode_1).unwrap(), inode_index_1);
- println!("Allcoated {} in inode {}", fs.allocate_block_for(&mut inode_2).unwrap(), inode_index_2);
+ for i in 0..DIRECT_NUMBER + INDIRECT_NUMBER {
+ println!(
+ "Allocated {} in inode {}",
+ fs.allocate_block_for(&mut inode_1).unwrap(),
+ inode_index_1
+ );
+ println!(
+ "Allocated {} in inode {}",
+ fs.allocate_block_for(&mut inode_2).unwrap(),
+ inode_index_2
+ );
}
let inode_index_3 = fs.create_inode(0o755, InodeMode::IFDIR, 0, 0, 0).unwrap();
let mut inode_3 = fs.get_inode(inode_index_3).unwrap().clone();
- for _i in 0 .. INDIRECT_NUMBER {
- println!("Deallcoated {} in inode {}", fs.deallocate_block_for(&mut inode_1).unwrap(), inode_index_1);
- println!("Allcoated {} in inode {}", fs.allocate_block_for(&mut inode_3).unwrap(), inode_index_3);
+ for _i in 0..INDIRECT_NUMBER {
+ println!(
+ "Deallocated {} in inode {}",
+ fs.deallocate_block_for(&mut inode_1).unwrap(),
+ inode_index_1
+ );
+ println!(
+ "Allocated {} in inode {}",
+ fs.allocate_block_for(&mut inode_3).unwrap(),
+ inode_index_3
+ );
}
- for _i in 0 .. DIRECT_NUMBER {
- println!("Deallcoated {} in inode {}", fs.deallocate_block_for(&mut inode_1).unwrap(), inode_index_1);
+ for _i in 0..DIRECT_NUMBER {
+ println!(
+ "Deallocated {} in inode {}",
+ fs.deallocate_block_for(&mut inode_1).unwrap(),
+ inode_index_1
+ );
}
assert!(fs.deallocate_block_for(&mut inode_1).is_none());
- println!("single indirect is {} for {}", inode_1.single_indirect, inode_index_1);
- println!("double indirect is {} for {}", inode_1.double_indirect, inode_index_1);
- println!("single indirect is {} for {}", inode_2.single_indirect, inode_index_2);
- println!("double indirect is {} for {}", inode_2.double_indirect, inode_index_2);
- println!("single indirect is {} for {}", inode_3.single_indirect, inode_index_3);
- println!("double indirect is {} for {}", inode_3.double_indirect, inode_index_3);
-
- assert_eq!(fs.data_bitmap.query(inode_1.single_indirect as usize), false);
+ println!(
+ "single indirect is {} for {}",
+ inode_1.single_indirect, inode_index_1
+ );
+ println!(
+ "double indirect is {} for {}",
+ inode_1.double_indirect, inode_index_1
+ );
+ println!(
+ "single indirect is {} for {}",
+ inode_2.single_indirect, inode_index_2
+ );
+ println!(
+ "double indirect is {} for {}",
+ inode_2.double_indirect, inode_index_2
+ );
+ println!(
+ "single indirect is {} for {}",
+ inode_3.single_indirect, inode_index_3
+ );
+ println!(
+ "double indirect is {} for {}",
+ inode_3.double_indirect, inode_index_3
+ );
+
+ assert_eq!(
+ fs.data_bitmap.query(inode_1.single_indirect as usize),
+ false
+ );
assert!(fs.data_bitmap.query(inode_2.single_indirect as usize));
- assert_eq!(fs.data_bitmap.query(inode_2.double_indirect as usize), false);
+ assert_eq!(
+ fs.data_bitmap.query(inode_2.double_indirect as usize),
+ false
+ );
assert!(fs.data_bitmap.query(inode_3.single_indirect as usize));
- assert_eq!(fs.data_bitmap.query(inode_3.double_indirect as usize), false);
+ assert_eq!(
+ fs.data_bitmap.query(inode_3.double_indirect as usize),
+ false
+ );
fs.allocate_block_for(&mut inode_2).unwrap();
println!("-----------------");
- println!("double indirect is {} for {}", inode_2.double_indirect, inode_index_2);
+ println!(
+ "double indirect is {} for {}",
+ inode_2.double_indirect, inode_index_2
+ );
assert!(fs.data_bitmap.query(inode_2.double_indirect as usize));
- for _i in 0 .. DIRECT_NUMBER {
+ for _i in 0..DIRECT_NUMBER {
fs.allocate_block_for(&mut inode_3).unwrap();
}
println!("-----------------");
- println!("double indirect is {} for {}", inode_3.double_indirect, inode_index_3);
- assert_eq!(fs.data_bitmap.query(inode_3.double_indirect as usize), false);
+ println!(
+ "double indirect is {} for {}",
+ inode_3.double_indirect, inode_index_3
+ );
+ assert_eq!(
+ fs.data_bitmap.query(inode_3.double_indirect as usize),
+ false
+ );
fs.allocate_block_for(&mut inode_3).unwrap();
println!("-----------------");
- println!("double indirect is {} for {}", inode_3.double_indirect, inode_index_3);
+ println!(
+ "double indirect is {} for {}",
+ inode_3.double_indirect, inode_index_3
+ );
assert!(fs.data_bitmap.query(inode_3.double_indirect as usize));
fs.update_inode(inode_index_1, inode_1);
fs.update_inode(inode_index_2, inode_2);
fs.update_inode(inode_index_3, inode_3);
-} \ No newline at end of file
+}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 2ea25e7..60b09f2 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -1,15 +1,48 @@
-use crate::disk::inode::INODE_SIZE;
+use crate::block_device::BLOCK_SIZE;
+use crate::disk::inode::{Inode, INODE_SIZE};
use crate::{AyaFS, INODE_PER_BLOCK};
-use std::time::{SystemTime, UNIX_EPOCH};
+use fuser::FileAttr;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
-impl AyaFS {
- pub(crate) fn time_now() -> u32 {
- SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .expect("How can current time be earlier than UNIX_EPOCH?")
- .as_secs() as u32
+pub(crate) fn time_now() -> u32 {
+ SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .expect("How can current time be earlier than UNIX_EPOCH?")
+ .as_secs() as u32
+}
+
+pub(crate) fn from_systime(system_time: SystemTime) -> u32 {
+ system_time
+ .duration_since(UNIX_EPOCH)
+ .expect("How can current time be earlier than UNIX_EPOCH?")
+ .as_secs() as u32
+}
+
+pub(crate) fn make_fileattr(inode_index: usize, inode: &Inode) -> FileAttr {
+ FileAttr {
+ ino: inode_index as u64,
+ size: inode.size as u64,
+ blocks: inode.n_blocks as u64,
+ atime: to_systime(inode.atime),
+ mtime: to_systime(inode.atime),
+ ctime: to_systime(inode.ctime),
+ crtime: to_systime(inode.crtime),
+ kind: inode.mode.into(),
+ perm: inode.mode.perm(),
+ nlink: inode.n_links as u32,
+ uid: inode.uid,
+ gid: inode.gid,
+ rdev: 0, // 我们不会遇到这个的
+ blksize: BLOCK_SIZE as u32,
+ flags: inode.flags,
}
+}
+
+pub(crate) fn to_systime(time: u32) -> SystemTime {
+ UNIX_EPOCH + Duration::from_secs(time as u64)
+}
+impl AyaFS {
/// 输入 inode 编号, 返回它对应的 block number 和 block 内 offset
pub(crate) fn locate_inode(&self, inode_index: usize) -> (usize, usize) {
let block_number =