diff options
-rw-r--r-- | Cargo.lock | 54 | ||||
-rw-r--r-- | Cargo.toml | 22 | ||||
-rw-r--r-- | ayafs/Cargo.toml | 18 | ||||
-rw-r--r-- | ayafs/src/block_device/disk.rs | 47 | ||||
-rw-r--r-- | ayafs/src/block_device/memory_disk.rs (renamed from src/block_device/memory_disk.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/block_device/mod.rs (renamed from src/block_device/mod.rs) | 2 | ||||
-rw-r--r-- | ayafs/src/disk/allocation.rs (renamed from src/disk/allocation.rs) | 38 | ||||
-rw-r--r-- | ayafs/src/disk/bitmap.rs (renamed from src/disk/bitmap.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/disk/block.rs (renamed from src/disk/block.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/disk/inode.rs (renamed from src/disk/inode.rs) | 2 | ||||
-rw-r--r-- | ayafs/src/disk/mod.rs (renamed from src/disk/mod.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/filesystem/mod.rs (renamed from src/filesystem/mod.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/filesystem/trait_impl.rs (renamed from src/filesystem/trait_impl.rs) | 555 | ||||
-rw-r--r-- | ayafs/src/main.rs (renamed from src/main.rs) | 23 | ||||
-rw-r--r-- | ayafs/src/memory/cached_block.rs (renamed from src/memory/cached_block.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/memory/cached_inode.rs (renamed from src/memory/cached_inode.rs) | 5 | ||||
-rw-r--r-- | ayafs/src/memory/dir_entry.rs (renamed from src/memory/dir_entry.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/memory/file_handle.rs (renamed from src/memory/file_handle.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/memory/mod.rs (renamed from src/memory/mod.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/tests/bitmap.rs (renamed from src/tests/bitmap.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/tests/block_cache.rs (renamed from src/tests/block_cache.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/tests/common/mod.rs (renamed from src/tests/common/mod.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/tests/mod.rs (renamed from src/tests/mod.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/utils/constants.rs (renamed from src/utils/constants.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/utils/mod.rs (renamed from src/utils/mod.rs) | 0 | ||||
-rw-r--r-- | ayafs/src/utils/permissions.rs (renamed from src/utils/permissions.rs) | 0 | ||||
-rw-r--r-- | mkfs.aya/Cargo.toml | 8 | ||||
-rw-r--r-- | mkfs.aya/src/block_device.rs | 5 | ||||
-rw-r--r-- | mkfs.aya/src/main.rs | 21 | ||||
-rw-r--r-- | rust-toolchain | 1 |
30 files changed, 457 insertions, 344 deletions
@@ -84,6 +84,22 @@ dependencies = [ ] [[package]] +name = "ayafs" +version = "0.1.0" +dependencies = [ + "and_then_some", + "bitflags", + "clap", + "env_logger", + "fuser", + "indexmap", + "libc", + "log", + "lru", + "users", +] + +[[package]] name = "bitflags" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -103,9 +119,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.4.6" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" dependencies = [ "clap_builder", "clap_derive", @@ -113,9 +129,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" dependencies = [ "anstream", "anstyle", @@ -125,9 +141,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -137,9 +153,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colorchoice" @@ -149,9 +165,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -242,9 +258,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "linux-raw-sys" @@ -260,9 +276,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efa59af2ddfad1854ae27d75009d538d0998b4b2fd47083e743ac1a10e46c60" +checksum = "2994eeba8ed550fd9b47a0b38f0242bc3344e496483c6180b69139cc2fa5d1d7" dependencies = [ "hashbrown", ] @@ -274,18 +290,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] -name = "myfs" +name = "mkayafs" version = "0.1.0" dependencies = [ - "and_then_some", - "bitflags", "clap", - "env_logger", - "fuser", - "indexmap", - "libc", - "log", - "lru", "users", ] @@ -1,18 +1,6 @@ -[package] -name = "myfs" -version = "0.1.0" -edition = "2021" +[workspace] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -and_then_some = "1.0.0" -bitflags = "2.4.0" -clap = { version = "4.4.6", features = ["derive"] } -env_logger = "0.10.0" -fuser = "0.14.0" -indexmap = "2.1.0" -libc = "0.2.148" -log = "0.4.20" -lru = "0.12.0" -users = "0.11.0" +members = [ + "ayafs", + "mkfs.aya", +] diff --git a/ayafs/Cargo.toml b/ayafs/Cargo.toml new file mode 100644 index 0000000..43585e0 --- /dev/null +++ b/ayafs/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "ayafs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +and_then_some = "1.0.0" +bitflags = "2.4.1" +clap = { version = "4.4.10", features = ["derive"] } +env_logger = "0.10.1" +fuser = "0.14.0" +indexmap = "2.1.0" +libc = "0.2.150" +log = "0.4.20" +lru = "0.12.1" +users = "0.11.0" diff --git a/ayafs/src/block_device/disk.rs b/ayafs/src/block_device/disk.rs new file mode 100644 index 0000000..3f0b018 --- /dev/null +++ b/ayafs/src/block_device/disk.rs @@ -0,0 +1,47 @@ +use std::cell::RefCell; +use std::fs::File; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::path::{Path, PathBuf}; +use crate::block_device::{BLOCK_SIZE, BlockDevice}; + +pub struct Disk { + 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), + } + } +} + +impl BlockDevice for Disk { + fn read(&self, block_id: usize, buffer: &mut [u8]) { + let mut device = self.device.borrow_mut(); + device + .seek(SeekFrom::Start((block_id * BLOCK_SIZE) as u64)) + .expect("Unable to seek!"); + device + .read_exact(buffer) + .expect("Failed to read 4096 bytes!"); + } + + fn write(&self, block_id: usize, buffer: &[u8]) { + let mut device = self.device.borrow_mut(); + device + .seek(SeekFrom::Start((block_id * BLOCK_SIZE) as u64)) + .expect("Unable to seek!"); + device + .write_all(buffer) + .expect("Unable to write 4096 bytes!"); + } +}
\ No newline at end of file diff --git a/src/block_device/memory_disk.rs b/ayafs/src/block_device/memory_disk.rs index 0639d3e..0639d3e 100644 --- a/src/block_device/memory_disk.rs +++ b/ayafs/src/block_device/memory_disk.rs diff --git a/src/block_device/mod.rs b/ayafs/src/block_device/mod.rs index a8fd8b7..a1e6544 100644 --- a/src/block_device/mod.rs +++ b/ayafs/src/block_device/mod.rs @@ -1,6 +1,8 @@ /// Abstracts for block devices. /// Currently only a mock memory disk. pub mod memory_disk; +pub mod disk; + pub const BLOCK_SIZE: usize = 4096; pub trait BlockDevice { fn read(&self, block_id: usize, buffer: &mut [u8]); diff --git a/src/disk/allocation.rs b/ayafs/src/disk/allocation.rs index d0142c9..a187fad 100644 --- a/src/disk/allocation.rs +++ b/ayafs/src/disk/allocation.rs @@ -1,9 +1,9 @@ use crate::disk::block::{ Block, DataBlock, DoubleIndirectBlock, IndirectBlock, TripleIndirectBlock, }; -use crate::disk::inode::{Inode, DIRECT_NUMBER}; +use crate::disk::inode::{Inode, DIRECT_NUMBER, ENTRY_PER_BLOCK}; use crate::memory::cached_block::{convert, CachedBlock}; -use crate::{AyaFS, INODE_PER_BLOCK}; +use crate::AyaFS; use libc::c_int; use log::debug; @@ -59,7 +59,7 @@ impl AyaFS { { // println!("allocating {} in double indirect", block_index); inode.n_blocks += 1; - let index_within_block = DIRECT_NUMBER + INODE_PER_BLOCK + index_within_double; + let index_within_block = DIRECT_NUMBER + ENTRY_PER_BLOCK + index_within_double; return Some((block_index, index_within_block)); } @@ -79,8 +79,8 @@ impl AyaFS { // println!("allocating {} in triple indirect", block_index); inode.n_blocks += 1; let index_within_block = DIRECT_NUMBER - + INODE_PER_BLOCK - + INODE_PER_BLOCK * INODE_PER_BLOCK + + ENTRY_PER_BLOCK + + ENTRY_PER_BLOCK * ENTRY_PER_BLOCK + index_within_triple; return Some((block_index, index_within_block)); } @@ -142,7 +142,7 @@ impl AyaFS { self.update_block(double_indirect_block); } let index_within_double = - index_within_double_indirect * INODE_PER_BLOCK + index_within_indirect; + index_within_double_indirect * ENTRY_PER_BLOCK + index_within_indirect; return Some((block_index, index_within_double)); } } @@ -180,7 +180,7 @@ impl AyaFS { self.update_block(triple_indirect_block); } let index_within_triple = - index_within_triple_indirect * INODE_PER_BLOCK * INODE_PER_BLOCK + index_within_triple_indirect * ENTRY_PER_BLOCK * ENTRY_PER_BLOCK + index_within_double_indirect; return Some((block_index, index_within_triple)); } @@ -424,7 +424,7 @@ impl AyaFS { } // indirect block - let indirect_number = 1024; + let indirect_number = ENTRY_PER_BLOCK; if block_index_within_inode < indirect_number { return if let Some(indirect_block) = self.get_block::<IndirectBlock>(inode.single_indirect as usize) @@ -432,10 +432,10 @@ impl AyaFS { debug!(" get_block_index -> indirect"); let block_index = indirect_block.block.entries[block_index_within_inode] as usize; if self.data_bitmap.query(block_index) { - debug!(" get_block_index -> indirect -> direct -> ✓"); + debug!(" get_block_index -> indirect -> ✓"); Some(block_index) } else { - debug!(" get_block_index -> indirect -> direct -> ×"); + debug!(" get_block_index -> indirect -> ×"); None } } else { @@ -447,25 +447,29 @@ impl AyaFS { } // double indirect block - let double_indirect_number = 1024 * 1024; + let double_indirect_number = ENTRY_PER_BLOCK * ENTRY_PER_BLOCK; if block_index_within_inode < double_indirect_number { if let Some(double_indirect_block) = self.get_block::<DoubleIndirectBlock>(inode.double_indirect as usize) { + debug!(" get_block_index -> double_indirect"); // 取出 double indirect block let indirect_block_index = double_indirect_block.block.indirect - [block_index_within_inode / INODE_PER_BLOCK] + [block_index_within_inode / ENTRY_PER_BLOCK] as usize; // 要找的 entry 在 double indirect block 中的第几个 indirect block if let Some(indirect_block) = self.get_block::<IndirectBlock>(indirect_block_index) { + debug!(" get_block_index -> double_indirect -> indirect"); let block_index = indirect_block.block.entries - [block_index_within_inode % INODE_PER_BLOCK] + [block_index_within_inode % ENTRY_PER_BLOCK] as usize; // 拿到 DirectoryBlock 的 index return if self.data_bitmap.query(block_index) { + debug!(" get_block_index -> double_indirect -> indirect -> ✓"); Some(block_index) } else { + debug!(" get_block_index -> double_indirect -> indirect -> ×"); None }; } @@ -481,7 +485,7 @@ impl AyaFS { { // 取出 triple indirect block let double_indirect_block_index = triple_indirect_block.block.double_indirect - [block_index_within_inode / (INODE_PER_BLOCK * INODE_PER_BLOCK)] + [block_index_within_inode / (ENTRY_PER_BLOCK * ENTRY_PER_BLOCK)] as usize; // 要找的 entry 在 triple indirect block 中的第几个 double indirect block if let Some(double_indirect_block) = @@ -489,13 +493,13 @@ impl AyaFS { { // 取出 double indirect block let indirect_block_index = double_indirect_block.block.indirect - [block_index_within_inode % (INODE_PER_BLOCK * INODE_PER_BLOCK) - / INODE_PER_BLOCK] as usize; + [block_index_within_inode % (ENTRY_PER_BLOCK * ENTRY_PER_BLOCK) + / ENTRY_PER_BLOCK] as usize; // 要找的 entry 在 double indirect block 中的第几个 indirect block if let Some(indirect_block) = self.get_block::<IndirectBlock>(indirect_block_index) { let block_index = indirect_block.block.entries - [block_index_within_inode % INODE_PER_BLOCK] + [block_index_within_inode % ENTRY_PER_BLOCK] as usize; // DirectoryBlock 的 index return if self.data_bitmap.query(block_index) { diff --git a/src/disk/bitmap.rs b/ayafs/src/disk/bitmap.rs index b68c341..b68c341 100644 --- a/src/disk/bitmap.rs +++ b/ayafs/src/disk/bitmap.rs diff --git a/src/disk/block.rs b/ayafs/src/disk/block.rs index 73819e2..73819e2 100644 --- a/src/disk/block.rs +++ b/ayafs/src/disk/block.rs diff --git a/src/disk/inode.rs b/ayafs/src/disk/inode.rs index e686d01..0c801ad 100644 --- a/src/disk/inode.rs +++ b/ayafs/src/disk/inode.rs @@ -1,6 +1,7 @@ use crate::utils; use bitflags::bitflags; use fuser::FileType; +use crate::block_device::BLOCK_SIZE; pub const DIRECT_NUMBER: usize = 15; @@ -308,3 +309,4 @@ impl Inode { } } pub const INODE_SIZE: usize = std::mem::size_of::<Inode>(); +pub const ENTRY_PER_BLOCK: usize = BLOCK_SIZE / 4;
\ No newline at end of file diff --git a/src/disk/mod.rs b/ayafs/src/disk/mod.rs index 878e832..878e832 100644 --- a/src/disk/mod.rs +++ b/ayafs/src/disk/mod.rs diff --git a/src/filesystem/mod.rs b/ayafs/src/filesystem/mod.rs index 1eaa8e8..1eaa8e8 100644 --- a/src/filesystem/mod.rs +++ b/ayafs/src/filesystem/mod.rs diff --git a/src/filesystem/trait_impl.rs b/ayafs/src/filesystem/trait_impl.rs index e030f04..1c40b92 100644 --- a/src/filesystem/trait_impl.rs +++ b/ayafs/src/filesystem/trait_impl.rs @@ -1,8 +1,7 @@ use crate::block_device::BLOCK_SIZE; use crate::disk::block::DataBlock; use crate::disk::inode::InodeMode; -use crate::utils::permissions::get_groups; -use crate::utils::permissions::{check_access, clear_suid_sgid}; +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}; @@ -10,9 +9,9 @@ use fuser::{ FileType, Filesystem, KernelConfig, ReplyAttr, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyOpen, ReplyWrite, Request, TimeOrNow, }; -use libc::{c_int, link, write, EACCES, EBADF, EEXIST, EFAULT, EINVAL, EIO, EISDIR, ENAMETOOLONG, ENOENT, ENOSPC, ENOSYS, ENOTDIR, ENOTEMPTY, EPERM, IPOPT_OFFSET, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY, R_OK, S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK, RENAME_NOREPLACE, RENAME_EXCHANGE}; +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, R_OK, S_ISGID, S_ISUID, S_IXGRP, S_IXOTH, S_IXUSR, W_OK, RENAME_NOREPLACE, RENAME_EXCHANGE}; use log::debug; -use std::ffi::{OsStr, OsString}; +use std::ffi::OsStr; use std::os::unix::ffi::OsStrExt; use std::path::Path; use std::slice; @@ -253,154 +252,6 @@ impl Filesystem for AyaFS { } } - fn symlink( - &mut self, - req: &Request<'_>, - parent: u64, - link_name: &OsStr, - target: &Path, - reply: ReplyEntry, - ) { - debug!( - "symlink(parent: {}, name: {:?}, target: {:?})", - parent, link_name, target - ); - let parent = parent as usize; - - // let root_inode_index = 1usize; - // if let Some(root_inode) = self.get_inode(root_inode_index) { - // let mut curr_inode_index = root_inode_index; - // let mut curr_inode = root_inode.clone(); - // for segment in target.iter() { - // match self.lookup_name(curr_inode_index, &curr_inode, segment) { - // Ok((next_inode_index, _, next_inode)) => { - // curr_inode_index = next_inode_index as usize; - // curr_inode = next_inode; - // } - // Err(err_code) => { - // reply.error(err_code); - // return; - // } - // } - // } - // } else { - // reply.error(EIO); - // return; - // } - - if let Some(parent_inode) = self.get_inode(parent) { - if !check_access( - req.uid(), - req.gid(), - parent_inode.uid, - parent_inode.gid, - parent_inode.mode, - W_OK, - ) { - reply.error(EACCES); - return; - } - - if !parent_inode.is_dir() { - reply.error(ENOTDIR); - return; - } - - if link_name.len() > 255 { - reply.error(ENAMETOOLONG); - return; - } - - let target = target.as_os_str(); - let mut parent_inode = parent_inode.clone(); - if self.lookup_name(parent, &parent_inode, link_name).is_ok() { - reply.error(EEXIST); - return; - } - - if let Some((child_inode_index, child_inode)) = - self.create_symlink(0o777, req.uid(), req.gid(), 0) - { - let mut child_inode = child_inode.clone(); - child_inode.size = target.len() as u32; - if target.len() < 60 { - debug!("create_symlink: target length < 60, allocating in 'direct' section."); - let target_path = target.as_bytes(); - let copy_dst = unsafe { - let dst = (&mut child_inode.direct) as *mut u32 as *mut u8; - slice::from_raw_parts_mut(dst, target_path.len()) - }; - copy_dst.copy_from_slice(target_path); - } else { - debug!("create_symlink: target length >= 60, using original layout."); - let mut write_ptr = 0usize; - while write_ptr < target.len() { - let block_index = write_ptr / BLOCK_SIZE; - let offset = write_ptr % BLOCK_SIZE; - - let write_length_within_block = - if BLOCK_SIZE - offset < target.len() - write_ptr { - BLOCK_SIZE - offset - } else { - target.len() - write_ptr - }; - - if let Some(block) = - self.access_block_mut::<DataBlock>(&child_inode, block_index) - { - block.block.0[offset..offset + write_length_within_block] - .copy_from_slice( - &target.as_bytes() - [write_ptr..write_ptr + write_length_within_block], - ); - write_ptr += write_length_within_block; - } else { - if let Some((_block_index, block_index_within_inode)) = - self.allocate_block_for(&mut child_inode) - { - let block = self - .access_block_mut::<DataBlock>( - &child_inode, - block_index_within_inode, - ) - .unwrap(); - block.block.0[offset..offset + write_length_within_block] - .copy_from_slice( - &target.as_bytes() - [write_ptr..write_ptr + write_length_within_block], - ); - write_ptr += write_length_within_block; - } else { - reply.error(ENOSPC); - return; - } - } - } - } - - let file_attr = to_fileattr(child_inode_index, &child_inode); - self.update_inode(child_inode_index, child_inode); - - if let Err(err_code) = self.add_direntry( - parent, - &mut parent_inode, - child_inode_index, - link_name, - from_filetype(FileType::Symlink), - ) { - reply.error(err_code); - return; - } - self.update_inode(parent, parent_inode); - reply.entry(&TTL, &file_attr, 0); - } else { - reply.error(ENOSPC); - } - } else { - reply.error(ENOENT); - } - } - // 这啥语义啊?? fn readlink(&mut self, req: &Request<'_>, ino: u64, reply: ReplyData) { debug!("readlink(ino: {})", ino); @@ -463,132 +314,6 @@ impl Filesystem for AyaFS { } } - fn rename( - &mut self, - req: &Request<'_>, - parent: u64, - name: &OsStr, - new_parent: u64, - new_name: &OsStr, - flags: u32, - reply: ReplyEmpty, - ) { - debug!( - "rename(parent: {}, name: {:?}, new_parent: {}, new_name: {:?})", - parent, name, new_parent, new_name - ); - - let parent = parent as usize; - let new_parent = new_parent as usize; - if let Some(parent_inode) = self.get_inode(parent) { - if !check_access( - req.uid(), - req.gid(), - parent_inode.uid, - parent_inode.gid, - parent_inode.mode, - R_OK, - ) { - reply.error(EACCES); - return; - } - - if name.len() > 255 { - reply.error(ENAMETOOLONG); - return; - } - - let mut parent_inode = parent_inode.clone(); - match self.lookup_name(parent, &parent_inode, name) { - Ok((inode_index, entry_index, inode)) => { - if let Some(new_parent_inode) = self.get_inode(new_parent) { - if !check_access( - req.uid(), - req.gid(), - new_parent_inode.uid, - new_parent_inode.gid, - new_parent_inode.mode, - W_OK, - ) { - reply.error(EACCES); - return; - } - if new_name.len() > 255 { - reply.error(ENAMETOOLONG); - return; - } - - 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)) => { - // 新文件存在 - if flags & RENAME_NOREPLACE != 0 { // 指定 noreplace 之后不允许覆盖文件 - reply.error(EEXIST); - return; - } - if flags & RENAME_EXCHANGE != 0 { // 交换两个文件 - if let Err(err_code) = self.exchange_direntry( - parent, - &mut parent_inode, - name, - new_parent, - &mut new_parent_inode, - new_name - ) { - reply.error(err_code); - return; - } - } else { // 用新文件替换旧文件 - let dir_entry = self.get_direntry_by_name(parent, &parent_inode, name) - .unwrap(); - if let Err(err_code) = self.remove_direntry(parent, &mut parent_inode, name, entry_index) { - reply.error(err_code); - return; - } - if let Err(err_code) = self.remove_direntry(new_parent, &mut new_parent_inode, new_name, new_entry_index) { - reply.error(err_code); - return; - } - if let Err(err_code) = self.add_direntry_2(new_parent, &mut new_parent_inode, new_name, dir_entry) { - reply.error(err_code); - return; - } - } - reply.ok(); - }, - Err(ENOENT) => { // 新文件不存在, 删除旧的创建新的 - let dir_entry = self.get_direntry_by_name(parent, &parent_inode, name) - .unwrap(); - if let Err(err_code) = self.remove_direntry(parent, &mut parent_inode, name, entry_index) { - reply.error(err_code); - return; - } - if let Err(err_code) = self.add_direntry_2(new_parent, &mut new_parent_inode, new_name, dir_entry) { - reply.error(err_code); - return; - } - reply.ok(); - }, - Err(err_code) => { - // 其他 Err code - reply.error(err_code); - return; - } - } - } else { - reply.error(ENOENT); - } - }, - Err(err_code) => { - reply.error(err_code); - return; - } - } - } else { - reply.error(ENOENT); - } - } - fn mknod( &mut self, req: &Request<'_>, @@ -891,6 +616,280 @@ impl Filesystem for AyaFS { } } + fn symlink( + &mut self, + req: &Request<'_>, + parent: u64, + link_name: &OsStr, + target: &Path, + reply: ReplyEntry, + ) { + debug!( + "symlink(parent: {}, name: {:?}, target: {:?})", + parent, link_name, target + ); + let parent = parent as usize; + + // let root_inode_index = 1usize; + // if let Some(root_inode) = self.get_inode(root_inode_index) { + // let mut curr_inode_index = root_inode_index; + // let mut curr_inode = root_inode.clone(); + // for segment in target.iter() { + // match self.lookup_name(curr_inode_index, &curr_inode, segment) { + // Ok((next_inode_index, _, next_inode)) => { + // curr_inode_index = next_inode_index as usize; + // curr_inode = next_inode; + // } + // Err(err_code) => { + // reply.error(err_code); + // return; + // } + // } + // } + // } else { + // reply.error(EIO); + // return; + // } + + if let Some(parent_inode) = self.get_inode(parent) { + if !check_access( + req.uid(), + req.gid(), + parent_inode.uid, + parent_inode.gid, + parent_inode.mode, + W_OK, + ) { + reply.error(EACCES); + return; + } + + if !parent_inode.is_dir() { + reply.error(ENOTDIR); + return; + } + + if link_name.len() > 255 { + reply.error(ENAMETOOLONG); + return; + } + + let target = target.as_os_str(); + let mut parent_inode = parent_inode.clone(); + if self.lookup_name(parent, &parent_inode, link_name).is_ok() { + reply.error(EEXIST); + return; + } + + if let Some((child_inode_index, child_inode)) = + self.create_symlink(0o777, req.uid(), req.gid(), 0) + { + let mut child_inode = child_inode.clone(); + child_inode.size = target.len() as u32; + if target.len() < 60 { + debug!("create_symlink: target length < 60, allocating in 'direct' section."); + let target_path = target.as_bytes(); + let copy_dst = unsafe { + let dst = (&mut child_inode.direct) as *mut u32 as *mut u8; + slice::from_raw_parts_mut(dst, target_path.len()) + }; + copy_dst.copy_from_slice(target_path); + } else { + debug!("create_symlink: target length >= 60, using original layout."); + let mut write_ptr = 0usize; + while write_ptr < target.len() { + let block_index = write_ptr / BLOCK_SIZE; + let offset = write_ptr % BLOCK_SIZE; + + let write_length_within_block = + if BLOCK_SIZE - offset < target.len() - write_ptr { + BLOCK_SIZE - offset + } else { + target.len() - write_ptr + }; + + if let Some(block) = + self.access_block_mut::<DataBlock>(&child_inode, block_index) + { + block.block.0[offset..offset + write_length_within_block] + .copy_from_slice( + &target.as_bytes() + [write_ptr..write_ptr + write_length_within_block], + ); + write_ptr += write_length_within_block; + } else { + if let Some((_block_index, block_index_within_inode)) = + self.allocate_block_for(&mut child_inode) + { + let block = self + .access_block_mut::<DataBlock>( + &child_inode, + block_index_within_inode, + ) + .unwrap(); + block.block.0[offset..offset + write_length_within_block] + .copy_from_slice( + &target.as_bytes() + [write_ptr..write_ptr + write_length_within_block], + ); + write_ptr += write_length_within_block; + } else { + reply.error(ENOSPC); + return; + } + } + } + } + + let file_attr = to_fileattr(child_inode_index, &child_inode); + self.update_inode(child_inode_index, child_inode); + + if let Err(err_code) = self.add_direntry( + parent, + &mut parent_inode, + child_inode_index, + link_name, + from_filetype(FileType::Symlink), + ) { + reply.error(err_code); + return; + } + self.update_inode(parent, parent_inode); + reply.entry(&TTL, &file_attr, 0); + } else { + reply.error(ENOSPC); + } + } else { + reply.error(ENOENT); + } + } + + fn rename( + &mut self, + req: &Request<'_>, + parent: u64, + name: &OsStr, + new_parent: u64, + new_name: &OsStr, + flags: u32, + reply: ReplyEmpty, + ) { + debug!( + "rename(parent: {}, name: {:?}, new_parent: {}, new_name: {:?})", + parent, name, new_parent, new_name + ); + + let parent = parent as usize; + let new_parent = new_parent as usize; + if let Some(parent_inode) = self.get_inode(parent) { + if !check_access( + req.uid(), + req.gid(), + parent_inode.uid, + parent_inode.gid, + parent_inode.mode, + R_OK, + ) { + reply.error(EACCES); + return; + } + + if name.len() > 255 { + reply.error(ENAMETOOLONG); + return; + } + + let mut parent_inode = parent_inode.clone(); + match self.lookup_name(parent, &parent_inode, name) { + Ok((inode_index, entry_index, inode)) => { + if let Some(new_parent_inode) = self.get_inode(new_parent) { + if !check_access( + req.uid(), + req.gid(), + new_parent_inode.uid, + new_parent_inode.gid, + new_parent_inode.mode, + W_OK, + ) { + reply.error(EACCES); + return; + } + if new_name.len() > 255 { + reply.error(ENAMETOOLONG); + return; + } + + 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)) => { + // 新文件存在 + if flags & RENAME_NOREPLACE != 0 { // 指定 noreplace 之后不允许覆盖文件 + reply.error(EEXIST); + return; + } + if flags & RENAME_EXCHANGE != 0 { // 交换两个文件 + if let Err(err_code) = self.exchange_direntry( + parent, + &mut parent_inode, + name, + new_parent, + &mut new_parent_inode, + new_name + ) { + reply.error(err_code); + return; + } + } else { // 用新文件替换旧文件 + let dir_entry = self.get_direntry_by_name(parent, &parent_inode, name) + .unwrap(); + if let Err(err_code) = self.remove_direntry(parent, &mut parent_inode, name, entry_index) { + reply.error(err_code); + return; + } + if let Err(err_code) = self.remove_direntry(new_parent, &mut new_parent_inode, new_name, new_entry_index) { + reply.error(err_code); + return; + } + if let Err(err_code) = self.add_direntry_2(new_parent, &mut new_parent_inode, new_name, dir_entry) { + reply.error(err_code); + return; + } + } + reply.ok(); + }, + Err(ENOENT) => { // 新文件不存在, 删除旧的创建新的 + let dir_entry = self.get_direntry_by_name(parent, &parent_inode, name) + .unwrap(); + if let Err(err_code) = self.remove_direntry(parent, &mut parent_inode, name, entry_index) { + reply.error(err_code); + return; + } + if let Err(err_code) = self.add_direntry_2(new_parent, &mut new_parent_inode, new_name, dir_entry) { + reply.error(err_code); + return; + } + reply.ok(); + }, + Err(err_code) => { + // 其他 Err code + reply.error(err_code); + return; + } + } + } else { + reply.error(ENOENT); + } + }, + Err(err_code) => { + reply.error(err_code); + return; + } + } + } else { + reply.error(ENOENT); + } + } + fn open(&mut self, req: &Request<'_>, ino: u64, flags: i32, reply: ReplyOpen) { debug!("open(ino: {:#x?}, flags: {:#x?})", ino, flags); let (access_mask, read, write) = match flags & O_ACCMODE { diff --git a/src/main.rs b/ayafs/src/main.rs index 78f338a..db4a017 100644 --- a/src/main.rs +++ b/ayafs/src/main.rs @@ -8,11 +8,12 @@ mod utils; use clap::Parser; use fuser::MountOption; use indexmap::IndexMap; -use log::debug; +use log::{debug, LevelFilter}; use lru::LruCache; use std::collections::HashMap; use std::ffi::OsString; use std::num::NonZeroUsize; +use std::path::PathBuf; use std::sync::atomic::AtomicU64; use std::sync::Arc; use std::time::Duration; @@ -24,11 +25,14 @@ use disk::bitmap::Bitmap; use disk::block::DataBlock; use disk::inode::INODE_SIZE; use users::{get_current_gid, get_current_uid}; +use crate::block_device::disk::Disk; #[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)] @@ -140,17 +144,28 @@ impl AyaFS { } fn main() { - env_logger::init(); 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 mem_disk = Arc::new(MemoryDisk::new(16384)); - let filesystem = AyaFS::new(mem_disk, 16384); + let disk = Arc::new(Disk::new(PathBuf::from("/dev/nvme0n1p4"))); + // let disk = Arc::new(MemoryDisk::new(16384)); + let filesystem = AyaFS::new(disk, 7864320); fuser::mount2(filesystem, mount_point, &options).unwrap(); } diff --git a/src/memory/cached_block.rs b/ayafs/src/memory/cached_block.rs index c3d0338..c3d0338 100644 --- a/src/memory/cached_block.rs +++ b/ayafs/src/memory/cached_block.rs diff --git a/src/memory/cached_inode.rs b/ayafs/src/memory/cached_inode.rs index 16c40c2..2f26dde 100644 --- a/src/memory/cached_inode.rs +++ b/ayafs/src/memory/cached_inode.rs @@ -4,11 +4,6 @@ use crate::{utils, AyaFS}; use and_then_some::BoolExt; use fuser::FileType; use libc::{c_int, EIO, EISDIR, ENOENT, ENOTDIR, ENOTEMPTY}; -use log::{debug, error}; -use std::ffi::OsStr; -use std::os::unix::ffi::OsStrExt; -use std::path::Path; -use std::slice; impl AyaFS { pub(crate) fn create_file( diff --git a/src/memory/dir_entry.rs b/ayafs/src/memory/dir_entry.rs index c013e1e..c013e1e 100644 --- a/src/memory/dir_entry.rs +++ b/ayafs/src/memory/dir_entry.rs diff --git a/src/memory/file_handle.rs b/ayafs/src/memory/file_handle.rs index c821619..c821619 100644 --- a/src/memory/file_handle.rs +++ b/ayafs/src/memory/file_handle.rs diff --git a/src/memory/mod.rs b/ayafs/src/memory/mod.rs index d1f1ab8..d1f1ab8 100644 --- a/src/memory/mod.rs +++ b/ayafs/src/memory/mod.rs diff --git a/src/tests/bitmap.rs b/ayafs/src/tests/bitmap.rs index 1a43f09..1a43f09 100644 --- a/src/tests/bitmap.rs +++ b/ayafs/src/tests/bitmap.rs diff --git a/src/tests/block_cache.rs b/ayafs/src/tests/block_cache.rs index 52117b9..52117b9 100644 --- a/src/tests/block_cache.rs +++ b/ayafs/src/tests/block_cache.rs diff --git a/src/tests/common/mod.rs b/ayafs/src/tests/common/mod.rs index 3abfcb4..3abfcb4 100644 --- a/src/tests/common/mod.rs +++ b/ayafs/src/tests/common/mod.rs diff --git a/src/tests/mod.rs b/ayafs/src/tests/mod.rs index df442c1..df442c1 100644 --- a/src/tests/mod.rs +++ b/ayafs/src/tests/mod.rs diff --git a/src/utils/constants.rs b/ayafs/src/utils/constants.rs index 8b13789..8b13789 100644 --- a/src/utils/constants.rs +++ b/ayafs/src/utils/constants.rs diff --git a/src/utils/mod.rs b/ayafs/src/utils/mod.rs index 468ebdb..468ebdb 100644 --- a/src/utils/mod.rs +++ b/ayafs/src/utils/mod.rs diff --git a/src/utils/permissions.rs b/ayafs/src/utils/permissions.rs index 6773511..6773511 100644 --- a/src/utils/permissions.rs +++ b/ayafs/src/utils/permissions.rs diff --git a/mkfs.aya/Cargo.toml b/mkfs.aya/Cargo.toml new file mode 100644 index 0000000..c75e3cb --- /dev/null +++ b/mkfs.aya/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "mkayafs" +version = "0.1.0" +edition = "2021" + +[dependencies] +users = "0.11.0" +clap = { version = "4.4.10", features = ["derive"] }
\ No newline at end of file diff --git a/mkfs.aya/src/block_device.rs b/mkfs.aya/src/block_device.rs new file mode 100644 index 0000000..295b357 --- /dev/null +++ b/mkfs.aya/src/block_device.rs @@ -0,0 +1,5 @@ +pub(crate) const BLOCK_SIZE: usize = 4096; +pub(crate) trait BlockDevice { + fn read(&self, block_id: usize, buffer: &mut [u8]); + fn write(&self, block_id: usize, buffer: &[u8]); +}
\ No newline at end of file diff --git a/mkfs.aya/src/main.rs b/mkfs.aya/src/main.rs new file mode 100644 index 0000000..57ca3fc --- /dev/null +++ b/mkfs.aya/src/main.rs @@ -0,0 +1,21 @@ +mod block_device; + +use std::fs::File; +use std::path::PathBuf; +use clap::Parser; +use users::{get_current_gid, get_current_uid}; + +#[derive(Parser, Debug)] +#[command(author, version, about)] +struct Args { + block_device: Option<PathBuf>, + start_point: Option<usize>, + length: Option<usize>, +} + +fn main() { + let args = Args::parse(); + let device_path = args.block_device.unwrap(); + println!("{:?}", device_path.as_path()); + let mut device = File::open(device_path.as_path()).unwrap(); +}
\ No newline at end of file diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..870bbe4 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +stable
\ No newline at end of file |