diff --git a/ableos/Cargo.lock b/ableos/Cargo.lock index 5f88b6b..0eb2927 100644 --- a/ableos/Cargo.lock +++ b/ableos/Cargo.lock @@ -802,7 +802,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "versioning" version = "0.1.2" -source = "git+https://git.ablecorp.us/able/versioning#ef472283e6e7a2e395ee56434087b3a6fad53ff2" +source = "git+https://git.ablecorp.us/able/versioning#b86e53ab8461ee4f28807bf2254d543f6d8f4727" [[package]] name = "vga" diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 0dabb52..702afe4 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -41,6 +41,8 @@ test-args = [ "stdio", ] + + [dependencies] linked_list_allocator = "0.9.0" lliw = "0.2.0" diff --git a/ableos/src/arch/riscv/mod.rs b/ableos/src/arch/riscv/mod.rs index 643563e..8745d9d 100644 --- a/ableos/src/arch/riscv/mod.rs +++ b/ableos/src/arch/riscv/mod.rs @@ -70,3 +70,7 @@ pub fn shutdown() {} use crate::print; use crate::println; + +pub fn generate_process_pass() -> u128 { + 123 +} diff --git a/ableos/src/arch/x86_64/init.rs b/ableos/src/arch/x86_64/init.rs index 4aa0778..28a3290 100644 --- a/ableos/src/arch/x86_64/init.rs +++ b/ableos/src/arch/x86_64/init.rs @@ -1,5 +1,9 @@ // #![allow(clippy::print_literal)] -use crate::{logger, scheduler::SCHEDULER, serial_println}; +use crate::{ + logger, + scheduler::{capabilities::Capabilities, SCHEDULER}, + serial_println, +}; use super::{gdt, interrupts}; @@ -20,10 +24,17 @@ pub fn init() { } gdt::init(); - use crate::scheduler::Priority::High; + use crate::scheduler::priority::Priority::High; + use crate::stdio::StdIO; let mut scheduler = SCHEDULER.lock(); - let process_0 = scheduler.new_process(High); + let process_0 = scheduler.new_process( + Capabilities::empty(), + High, + "".to_string(), + StdIO::new(crate::stdio::Device::VTerm), + ); scheduler.add_process(process_0); + drop(scheduler); interrupts::init_idt(); diff --git a/ableos/src/arch/x86_64/mod.rs b/ableos/src/arch/x86_64/mod.rs index be828ac..56392d4 100644 --- a/ableos/src/arch/x86_64/mod.rs +++ b/ableos/src/arch/x86_64/mod.rs @@ -47,3 +47,13 @@ pub fn sloop() -> ! { hlt(); } } + +// TODO: Split up into the randomness and the password generation +pub fn generate_process_pass() -> u128 { + // TODO: Move this into entropy_pool module + use rdrand::RdRand; + let gen = RdRand::new().unwrap(); + + let ret = (gen.try_next_u64().unwrap() as u128) << 64 | (gen.try_next_u64().unwrap() as u128); + ret +} diff --git a/ableos/src/driver_traits/serial.rs b/ableos/src/driver_traits/serial.rs index 6ffc40a..075d686 100644 --- a/ableos/src/driver_traits/serial.rs +++ b/ableos/src/driver_traits/serial.rs @@ -1,4 +1,35 @@ -pub trait Serial { - fn print(); - fn recieve(); +use kernel::device_interface::character::CharacterDevice; + +pub struct Serial { + pub base: usize, +} +impl CharacterDevice for Serial { + fn can_read(&self) -> bool { + true + } + + fn can_write(&self) -> bool { + true + } + + fn read_char(&mut self) -> Option { + todo!() + } + + fn write_char(&mut self, c: char) -> bool { + todo!() + } + + fn reset(&mut self) { + todo!() + } + + fn initialize(&mut self) -> bool { + false + } +} +pub fn new_serial_test() { + let mut serial = Serial { base: 0x3F8 }; + serial.initialize(); + serial.write_char('a'); } diff --git a/ableos/src/experiments/mod.rs b/ableos/src/experiments/mod.rs index e35a19c..f05b28c 100644 --- a/ableos/src/experiments/mod.rs +++ b/ableos/src/experiments/mod.rs @@ -4,6 +4,7 @@ pub mod absi; pub mod clip; pub mod futex; // pub mod info; +pub mod info; pub mod kinfo; pub mod mail; pub mod server; diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index 7260574..95988a1 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -30,13 +30,10 @@ pub fn kernel_main() -> ! { log::set_max_level(log::LevelFilter::Off); } let mut scheduler = SCHEDULER.lock(); - use crate::scheduler::Priority::*; - let mut process_1 = scheduler.new_process(High); - process_1.capabilities.files = FileAccess::Some(vec![]); - scheduler.add_process(process_1); - for ref_process in &scheduler.list { - trace!("{:?}", ref_process); + for proc in &scheduler.execution_queue { + trace!("{:?}", proc); } + drop(scheduler); // start_facepalm(); @@ -54,29 +51,18 @@ pub fn cpu_socket_startup() { } pub fn log_version_data() { - info!("{} v{:?}", RELEASE_TYPE, KERNEL_VERSION); + info!("{} v{}", RELEASE_TYPE, KERNEL_VERSION); info!( - "Brand String: ", - // master().unwrap().brand_string().unwrap() + "Brand String: {}", + master().unwrap().brand_string().unwrap() ); } -// TODO: Split up into the randomness and the password generation -pub fn generate_process_pass() -> u128 { - // TODO: Move this into entropy_pool module - // use rdrand::RdRand; - // let gen = RdRand::new().unwrap(); - - // TODO: Split off into process module - // let ret = (gen.try_next_u64().unwrap() as u128) << 64 | (gen.try_next_u64().unwrap() as u128); - // ret - 123 -} +use crate::info::master; use kernel::KERNEL_VERSION; +use crate::scheduler::SCHEDULER; use crate::{ - boot_conf::KernelConfig, - scheduler::{capabilities::FileAccess, SCHEDULER}, - systeminfo::RELEASE_TYPE, + boot_conf::KernelConfig, scheduler::capabilities::FileAccess, systeminfo::RELEASE_TYPE, }; diff --git a/ableos/src/lib.rs b/ableos/src/lib.rs index 4a30abe..048e313 100644 --- a/ableos/src/lib.rs +++ b/ableos/src/lib.rs @@ -110,3 +110,5 @@ pub mod prelude; #[prelude_import] pub use prelude::rust_2021::*; + +pub mod stdio; diff --git a/ableos/src/rhai_shell/balloon.txt b/ableos/src/rhai_shell/balloon.txt new file mode 100644 index 0000000..0685083 --- /dev/null +++ b/ableos/src/rhai_shell/balloon.txt @@ -0,0 +1,11 @@ + ,-""""-. OS: AbleOS + ,' _ `. Host: {} + / )_) \ Kernel: AKern-{}-v{} +: : Uptime: {} +\ / Packages: None + \ / Shell: RhaiShell + `. ,' Resolution: 640x480 + `. ,' Terminal: VGABuffer + `.,' CPU: {} + /\`. ,-._ GPU: VGA Compatible + `-' Memory: {}/{} \ No newline at end of file diff --git a/ableos/src/rhai_shell/mod.rs b/ableos/src/rhai_shell/mod.rs index 8c26922..47b4034 100644 --- a/ableos/src/rhai_shell/mod.rs +++ b/ableos/src/rhai_shell/mod.rs @@ -35,9 +35,12 @@ lazy_static::lazy_static!( ); use rhai::Engine; +use x86_64::instructions::interrupts::{disable, enable}; +use crate::info::master; use crate::time::fetch_time; use crate::wasm_jumploader::interp; +use crate::{allocator, ALLOCATOR}; use crate::{ arch::{shutdown, sloop}, systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, @@ -49,14 +52,24 @@ pub fn afetch() { let tick_time = fetch_time(); - println!( - "OS: AbleOS -Host: {} -Kernel: AKern-{}-v{} -Uptime: {}", - kstate.hostname, RELEASE_TYPE, KERNEL_VERSION, tick_time - ); + disable(); + let allocator = ALLOCATOR.lock(); + let size = allocator.size(); + let used = allocator.used(); + enable(); + // let mem = format!("{}/{}", used, size); + println!( + include_str!("balloon.txt"), + kstate.hostname, + RELEASE_TYPE, + KERNEL_VERSION, + tick_time, + master().unwrap().brand_string().unwrap(), + // mem + used, + size + ); drop(kstate); } pub fn set_hostname(name: String) { diff --git a/ableos/src/scheduler/mod.rs b/ableos/src/scheduler/mod.rs index 9449181..db65e03 100644 --- a/ableos/src/scheduler/mod.rs +++ b/ableos/src/scheduler/mod.rs @@ -1,197 +1,96 @@ -// #![warn(missing_docs)] +use crate::{arch::generate_process_pass, stdio::StdIO}; -//! The standard ableOS scheduler named -//! -//! # Notes -//! The scheduler is also responsible for choosing the priority of a process. -//! The scheduler is responsible for choosing which process to execute next. +use crate::scheduler::capabilities::Capabilities; +use kernel::proccess::PID; pub mod capabilities; +pub mod priority; pub mod proc; - -mod new_sched; -use proc::{Process, PID}; - -#[cfg(test)] -mod tests; - -use crate::kmain::generate_process_pass; - -use self::capabilities::Capabilities; - -lazy_static::lazy_static!( - /// The standard implementation for ableOS - pub static ref SCHEDULER: spin::Mutex = spin::Mutex::new(Scheduler::new()); - -); - -/// Scheduler priority model -#[derive(Clone, Copy, Debug)] -pub enum Priority { - /// Exclusively Kernel space | 20 Timer Tick execution time - High, - /// Kernel / User space | 15 Timer Tick execution time - Medium, - /// low priority userspace code | 10 Timer Tick execution time - Low, +use priority::Priority; +use proc::Process; +/// Add additional wake conditions to the list +#[derive(Clone, Debug)] +pub enum WakeCondition { + /// Wake when the process has been blocked for a certain amount of time + TimerInterrupt(u64), + SocketRead(PID), + SocketWrite(PID), + SocketOpen(PID), + SocketClose(PID), + // HardwareEvent, } +// NOTE: Define what is a sleeping process in the context of the ableOS kernel. +// Blocked processes are processes that are waiting for a certain event to occur. #[derive(Clone, Debug)] -pub enum FileAccessTypes { - All, - Some(Vec), - None, +pub struct BlockedProcess { + pub pid: PID, + pub wake_condition: WakeCondition, } -/// This structure handles the process scheduling and execution -/// -/// # Example -/// ``` -/// use crate::scheduler::Priority; -/// use crate::scheduler::Scheduler; -/// -/// let mut scheduler = Scheduler::new(); -/// -/// let pid = scheduler.new_process(Priority::High); -/// scheduler.run_process(pid); -/// ``` -#[derive(Clone, Debug)] pub struct Scheduler { - /// The highest free process ID pub free_pid: PID, - /// The execution time of the current process in ticks pub process_exec_time: u64, - /// The list of processes - pub list: Vec, + pub execution_queue: Vec, + pub sleeping_queue: Vec, + pub blocked_queue: Vec, + // / All timed processes sorted by wake time } - impl Scheduler { /// Create a new scheduler - /// - /// # Example - /// ``` - /// use ableos::scheduler::Priority; - /// let mut scheduler = Scheduler::new(); - /// ``` pub fn new() -> Self { Self { - free_pid: PID(0), + free_pid: 0, process_exec_time: 0, - list: Vec::new(), + execution_queue: Vec::new(), + sleeping_queue: Vec::new(), + blocked_queue: Vec::new(), } } /// Change the current process to the next process in the list - /// - /// # Example - /// - /// ``` - /// let mut scheduler = scheduler(); - /// let mut process = scheduler.next_process(); - /// ``` - /// - /// # Panics - /// - /// Panics if there are no processes in the list pub fn next_process(&mut self) { self.process_exec_time = 0; - let previous_task = self.list[0].clone(); - self.list.remove(0); - self.list.push(previous_task); + let previous_task = self.execution_queue[0].clone(); + self.execution_queue.remove(0); + self.execution_queue.push(previous_task); } - /// Creates a new process - /// - /// # Arguments - /// - /// * `priority` - The priority of the process - /// - /// # Example - /// - /// ``` - /// let mut scheduler = scheduler(); - /// let mut process = scheduler.new_process(Priority::Medium); - /// ``` - pub fn new_process(&mut self, priority: Priority) -> Process { - let process = Process { - id: self.free_pid.clone(), - password: generate_process_pass(), - capabilities: Capabilities::empty(), + pub fn add_process(&mut self, mut process: Process) { + process.pid = self.free_pid; + self.free_pid += 1; + self.execution_queue.push(process); + } + + pub fn new_process( + &mut self, + capabilities: Capabilities, + priority: Priority, + working_dir: String, + stdio: StdIO, + ) -> Process { + let mut process = Process { + pid: 0, priority, - working_dir: "todo!()".to_string(), + working_dir, + stdio, + password: generate_process_pass(), + capabilities, }; - // self.free_pid.0 += 1; - // self.list.push(process); process } - /// Add a created process to the scheduler - /// - /// # Arguments - /// - /// * `process` - The process to add - /// - /// # Example - /// - /// ``` - /// let mut scheduler = Scheduler::new(); - /// let mut process = scheduler.new_process(Priority::Medium); - /// scheduler.add_process(process); - /// ``` - pub fn add_process(&mut self, process: Process) { - self.list.push(process); - self.free_pid.0 += 1; - } - /// Terminate the process with the matching PID - /// - /// # Arguments - /// - /// * `pid` - The PID of the process to terminate - /// - /// # Example - /// - /// ``` - /// let mut scheduler = scheduler(); - /// let mut process = scheduler.new_process(Priority::Medium); - /// scheduler.terminate_process(process.id); - /// ``` - pub fn term_process(&mut self, pid: PID) { - let mut process_index = 0; - for x in &self.list { - if x.id == pid { - self.list.remove(process_index); - break; - } - process_index += 1 - } - } - /// Bump the current process' execution time - /// - /// # Example - /// - /// ``` - /// let mut scheduler = scheduler(); - /// let mut process = scheduler.new_process(Priority::Medium); - /// scheduler.bump_exec(); - /// ``` - pub fn bump_exec(&mut self) { - self.process_exec_time += 1; + pub fn sleep_process(&mut self, process: &mut Process) { + let sleeping_process = BlockedProcess { + pid: process.pid, + wake_condition: WakeCondition::TimerInterrupt(0), + }; - use Priority::*; - if self.list.len() > 0 { - match (self.process_exec_time, self.list[0].priority) { - (20, High) => { - self.next_process(); - } - (15, Medium) => { - self.next_process(); - } - (10, Low) => { - self.next_process(); - } - - (_, _) => {} - } - } + self.sleeping_queue.push(sleeping_process.clone()); + self.execution_queue.remove(0); } } + +lazy_static::lazy_static! { + pub static ref SCHEDULER: spin::Mutex = spin::Mutex::new(Scheduler::new()); +} diff --git a/ableos/src/scheduler/new_sched.rs b/ableos/src/scheduler/new_sched.rs deleted file mode 100644 index 4a39a93..0000000 --- a/ableos/src/scheduler/new_sched.rs +++ /dev/null @@ -1,86 +0,0 @@ -use crate::{ - kmain::generate_process_pass, - scheduler::capabilities::Capabilities, - scheduler::proc::{Process, PID}, - scheduler::Priority, -}; -/// Add additional wake conditions to the list -pub enum WakeCondition { - /// Wake when the process has been blocked for a certain amount of time - TimerInterrupt(u64), - SocketRead(PID), - SocketWrite(PID), - SocketOpen(PID), - SocketClose(PID), - // HardwareEvent, -} - -// NOTE: Define what is a sleeping process in the context of the ableOS kernel. -// Blocked processes are processes that are waiting for a certain event to occur. -pub struct BlockedProcess { - pub pid: PID, - pub wake_time: u64, -} - -pub struct Scheduler { - pub free_pid: PID, - pub process_exec_time: u64, - pub execution_queue: Vec, - pub sleeping_queue: Vec, - // pub blocked_queue: Vec, - // / All timed processes sorted by wake time - // pub timed_blocked_queue: Vec, -} -impl Scheduler { - /// Create a new scheduler - pub fn new() -> Self { - Self { - free_pid: PID(0), - process_exec_time: 0, - execution_queue: Vec::new(), - sleeping_queue: Vec::new(), - } - } - - /// Change the current process to the next process in the list - pub fn next_process(&mut self) { - self.process_exec_time = 0; - let previous_task = self.execution_queue[0].clone(); - self.execution_queue.remove(0); - self.execution_queue.push(previous_task); - } - - /// Creates a new process - /// # Arguments - /// * `priority` - The priority of the process - /// # Example - /// - /// ``` - /// let mut scheduler = scheduler(); - /// let mut process = scheduler.new_process(Priority::Medium); - /// ``` - /// - /// TODO: Add a priority queue - /// TODO: Add a process queue - pub fn new_process(&mut self, priority: Priority) -> Process { - let process = Process { - id: self.free_pid, - password: generate_process_pass(), - priority, - capabilities: Capabilities::empty(), - working_dir: "todo!()".to_string(), - }; - self.free_pid.0 += 1; - process - } - - pub fn sleep_process(&mut self, process: &mut Process) { - let sleeping_process = BlockedProcess { - pid: process.id, - wake_time: 0, - }; - - self.sleeping_queue.push(process.clone()); - self.execution_queue.remove(0); - } -} diff --git a/ableos/src/scheduler/priority.rs b/ableos/src/scheduler/priority.rs new file mode 100644 index 0000000..f74992f --- /dev/null +++ b/ableos/src/scheduler/priority.rs @@ -0,0 +1,10 @@ +/// Scheduler priority model +#[derive(Clone, Copy, Debug)] +pub enum Priority { + /// Exclusively Kernel space | 20 Timer Tick execution time + High, + /// Kernel / User space | 15 Timer Tick execution time + Medium, + /// low priority userspace code | 10 Timer Tick execution time + Low, +} diff --git a/ableos/src/scheduler/proc.rs b/ableos/src/scheduler/proc.rs index ee135a8..a41239b 100644 --- a/ableos/src/scheduler/proc.rs +++ b/ableos/src/scheduler/proc.rs @@ -1,17 +1,15 @@ //! Process definition and general utilities surrounding them -use super::{capabilities::Capabilities, Priority}; - -/// Process Identification -#[derive(Clone, Copy, PartialEq, Debug)] -#[repr(C)] -pub struct PID(pub usize); +use super::capabilities::Capabilities; +use super::priority::Priority; +use crate::stdio::StdIO; +use kernel::proccess::PID; /// A process #[derive(Clone, Debug)] pub struct Process { /// Internal PID - pub id: PID, + pub pid: PID, /// Process password pub password: u128, @@ -20,8 +18,9 @@ pub struct Process { /// A process's priority pub priority: Priority, - /// + /// A process's current working directory pub working_dir: String, + pub stdio: StdIO, } impl Process {} diff --git a/ableos/src/scheduler/tests.rs b/ableos/src/scheduler/tests.rs deleted file mode 100644 index f76799e..0000000 --- a/ableos/src/scheduler/tests.rs +++ /dev/null @@ -1,49 +0,0 @@ -use super::*; - -use crate::scheduler::{ - capabilities::{ControllerAccess, FileAccess, KeyboardAccess, MouseAccess, SoundCardAccess}, - proc::PID, - Priority::*, - Scheduler, -}; - -// #[test] -fn test_new_process() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - assert_eq!(scheduler.list.len(), 1); -} - -// #[test] -fn test_next_process() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - scheduler.next_process(); - assert_eq!(scheduler.list.len(), 0); -} - -// #[test] -fn test_term_process() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - scheduler.term_process(PID(1)); - assert_eq!(scheduler.list.len(), 0); -} - -// #[test] -fn test_bump_exec() { - let mut scheduler = Scheduler::new(); - scheduler.new_process(High); - scheduler.bump_exec(); - assert_eq!(scheduler.process_exec_time, 1); -} - -// #[test] -fn test_capabilities() { - let caps = Capabilities::empty(); - assert_eq!(caps.files, FileAccess::None); - assert_eq!(caps.mouse, MouseAccess::No); - assert_eq!(caps.keyboard, KeyboardAccess::No); - assert_eq!(caps.controllers, ControllerAccess::None); - assert_eq!(caps.sound_cards, SoundCardAccess::None); -} diff --git a/ableos/src/scratchpad.rs b/ableos/src/scratchpad.rs index 1f4e96e..395cb32 100644 --- a/ableos/src/scratchpad.rs +++ b/ableos/src/scratchpad.rs @@ -2,13 +2,17 @@ use acpi::AcpiTables; use crate::rhai_shell::shell; +use crate::stdio::StdIO; /// Experimental scratchpad for testing. pub fn scratchpad() { - // pci_fun(); + let mut stdio = StdIO::new(crate::stdio::Device::Serial); + stdio.write(); shell(); } +use core::fmt::Write; + pub fn pci_fun() {} pub fn acpi() { diff --git a/ableos/src/stdio.rs b/ableos/src/stdio.rs new file mode 100644 index 0000000..367909f --- /dev/null +++ b/ableos/src/stdio.rs @@ -0,0 +1,34 @@ +use core::fmt::Arguments; +use core::fmt::Error; +use core::fmt::Write; + +use crate::kprintln; + +#[derive(Debug, Clone, Copy)] +pub enum Device { + VTerm, + Serial, +} +#[derive(Debug, Clone, Copy)] +pub struct StdIO { + device: Device, +} + +impl StdIO { + pub fn new(device: Device) -> StdIO { + StdIO { device } + } + pub fn write(&mut self) { + match self.device { + Device::VTerm => { + println!("Hello, world!"); + } + Device::Serial => { + serial_println!("Hello, world!"); + } + } + } + pub fn read(&mut self) { + todo!(); + } +} diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock deleted file mode 100644 index b2f29bf..0000000 --- a/kernel/Cargo.lock +++ /dev/null @@ -1,22 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "kernel" -version = "0.1.2" -dependencies = [ - "lazy_static", - "versioning", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "versioning" -version = "0.1.2" -source = "git+https://git.ablecorp.us/able/versioning#ef472283e6e7a2e395ee56434087b3a6fad53ff2" diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 7ed790e..97cb8ef 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -8,6 +8,7 @@ pub mod device_interface; pub mod messaging; pub mod panic; pub mod proccess; +pub mod syscalls; pub mod time; use core::sync::atomic::{AtomicU64, Ordering::Relaxed}; diff --git a/kernel/src/proccess.rs b/kernel/src/proccess.rs index 7077cbd..90b9266 100644 --- a/kernel/src/proccess.rs +++ b/kernel/src/proccess.rs @@ -2,3 +2,12 @@ /// A process ID pub type PID = u64; + +#[repr(C)] +/// Signals that can be sent to a process +pub enum Signals { + /// Terminate the process + Terminate, + /// Shutdown the process and allow it to shutdown cleanly + Quit, +} diff --git a/kernel/src/syscalls.rs b/kernel/src/syscalls.rs new file mode 100644 index 0000000..1dd242f --- /dev/null +++ b/kernel/src/syscalls.rs @@ -0,0 +1,24 @@ +//! + +use crate::proccess::{Signals, PID}; +/// All possible system calls +pub enum Syscall { + /// Create a new process and return its PID + CreateProcess, + /// Send a signal to a process + SendSignal(PID, Signals), + + /// Get the current process ID + GetPID, + /// Get the current time + GetTime, + /// Set the time + SetTime, + /* + ListInodes, + CreateInode, + RemoveInode, + OpenInode, + CloseInode, + */ +}