From 269fd9abc042a861a1ffd2e6a339676952f3ec0b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 8 Mar 2025 21:41:33 +0100 Subject: [PATCH] storage/lived: Use the unified disk scheme implementation --- Cargo.lock | 2 +- storage/driver-block/src/lib.rs | 2 + storage/lived/Cargo.toml | 2 +- storage/lived/src/main.rs | 198 ++++++++++---------------------- 4 files changed, 66 insertions(+), 138 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9506ce08e1..d024866c9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -780,9 +780,9 @@ name = "lived" version = "0.1.0" dependencies = [ "anyhow", + "driver-block", "libredox", "redox-daemon", - "redox-scheme 0.3.0", "redox_event", "redox_syscall", ] diff --git a/storage/driver-block/src/lib.rs b/storage/driver-block/src/lib.rs index a60a208847..fa5b4fb22a 100644 --- a/storage/driver-block/src/lib.rs +++ b/storage/driver-block/src/lib.rs @@ -69,6 +69,8 @@ pub trait Disk { fn block_size(&self) -> u32; fn size(&self) -> u64; + // These operate on a whole multiple of the block size + // FIXME maybe only operate on a single block worth of data? fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result>; fn write(&mut self, block: u64, buffer: &[u8]) -> syscall::Result>; } diff --git a/storage/lived/Cargo.toml b/storage/lived/Cargo.toml index 57ec2be9fe..034ba80d0a 100644 --- a/storage/lived/Cargo.toml +++ b/storage/lived/Cargo.toml @@ -12,5 +12,5 @@ anyhow = "1" libredox = "0.1.3" redox-daemon = "0.1" redox_syscall = { version = "0.5", features = ["std"] } -redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } redox_event = "0.4" +driver-block = { path = "../driver-block" } diff --git a/storage/lived/src/main.rs b/storage/lived/src/main.rs index b2f9096600..f4c2ac15ff 100644 --- a/storage/lived/src/main.rs +++ b/storage/lived/src/main.rs @@ -2,46 +2,26 @@ #![feature(int_roundings)] +use std::collections::BTreeMap; use std::fs::File; use std::os::fd::AsRawFd; -use std::str; +use driver_block::{Disk, DiskScheme}; use libredox::call::MmapArgs; use libredox::flag; -use redox_scheme::{CallerCtx, OpenResult, RequestKind, Scheme, SignalBehavior, Socket}; -use syscall::data::Stat; use syscall::error::*; -use syscall::flag::{MODE_DIR, MODE_FILE}; -use syscall::schemev2::NewFdFlags; use syscall::PAGE_SIZE; use anyhow::{anyhow, bail, Context}; -const LIST: [u8; 2] = *b"0\n"; - -#[repr(usize)] -enum HandleType { - TopLevel = 0, - TheData = 1, -} -impl HandleType { - fn try_from_raw(raw: usize) -> Option { - Some(match raw { - 0 => Self::TopLevel, - 1 => Self::TheData, - _ => return None, - }) - } -} - -pub struct DiskScheme { +struct LiveDisk { the_data: &'static mut [u8], } -impl DiskScheme { - pub fn new() -> anyhow::Result { +impl LiveDisk { + fn new() -> anyhow::Result { let mut phys = 0; let mut size = 0; @@ -93,133 +73,79 @@ impl DiskScheme { std::slice::from_raw_parts_mut(base as *mut u8, size) }; - Ok(DiskScheme { the_data }) + Ok(LiveDisk { the_data }) } } -impl Scheme for DiskScheme { - fn fsize(&mut self, id: usize) -> Result { - Ok( - match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? { - HandleType::TopLevel => LIST.len() as u64, - HandleType::TheData => self.the_data.len() as u64, - }, - ) +impl Disk for LiveDisk { + fn block_size(&self) -> u32 { + 512 } - fn fcntl(&mut self, _id: usize, _cmd: usize, _arg: usize) -> Result { - Ok(0) + fn size(&self) -> u64 { + self.the_data.len() as u64 } - fn fsync(&mut self, _id: usize) -> Result { - Ok(0) - } - - fn close(&mut self, _id: usize) -> Result { - Ok(0) - } - fn xopen(&mut self, path: &str, _flags: usize, ctx: &CallerCtx) -> Result { - if ctx.uid != 0 { - return Err(Error::new(EACCES)); + fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result> { + let block = block as usize; + let block_size = self.block_size() as usize; + if block * block_size + buffer.len() > self.size() as usize { + return Err(syscall::Error::new(EOVERFLOW)); } - - let path_trimmed = path.trim_matches('/'); - - Ok(OpenResult::ThisScheme { - number: match path_trimmed { - "" => HandleType::TopLevel as usize, - "0" => HandleType::TheData as usize, - _ => return Err(Error::new(ENOENT)), - }, - flags: NewFdFlags::POSITIONED, - }) - } - fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _flags: u32) -> Result { - let data = match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? { - HandleType::TheData => &*self.the_data, - HandleType::TopLevel => &LIST, - }; - - let src = usize::try_from(offset) - .ok() - .and_then(|o| data.get(o..)) - .unwrap_or(&[]); - let byte_count = std::cmp::min(src.len(), buf.len()); - buf[..byte_count].copy_from_slice(&src[..byte_count]); - Ok(byte_count) - } - fn write(&mut self, id: usize, buf: &[u8], offset: u64, _flags: u32) -> Result { - let data = match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? { - HandleType::TheData => &mut *self.the_data, - HandleType::TopLevel => return Err(Error::new(EBADF)), - }; - - let dst = usize::try_from(offset) - .ok() - .and_then(|o| data.get_mut(o..)) - .unwrap_or(&mut []); - let byte_count = std::cmp::min(dst.len(), buf.len()); - dst[..byte_count].copy_from_slice(&buf[..byte_count]); - Ok(byte_count) + buffer + .copy_from_slice(&self.the_data[block * block_size..block * block_size + buffer.len()]); + Ok(Some(block_size)) } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let path = match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? { - HandleType::TopLevel => "", - HandleType::TheData => "0", - }; - - let src = format!("disk.live:{}", path).into_bytes(); - - let byte_count = std::cmp::min(buf.len(), src.len()); - buf[..byte_count].copy_from_slice(&src[..byte_count]); - - Ok(byte_count) - } - fn fstat(&mut self, id: usize, stat_buf: &mut Stat) -> Result { - let (len, mode) = match HandleType::try_from_raw(id).ok_or(Error::new(EBADF))? { - HandleType::TheData => (self.the_data.len(), MODE_FILE | 0o644), - HandleType::TopLevel => (LIST.len(), MODE_DIR | 0o755), - }; - - *stat_buf = Stat { - st_mode: mode, - st_uid: 0, - st_gid: 0, - st_size: len.try_into().map_err(|_| Error::new(EOVERFLOW))?, - ..Stat::default() - }; - - Ok(0) + fn write(&mut self, block: u64, buffer: &[u8]) -> syscall::Result> { + let block = block as usize; + let block_size = self.block_size() as usize; + if block * block_size + buffer.len() > self.size() as usize { + return Err(syscall::Error::new(EOVERFLOW)); + } + self.the_data[block * block_size..block * block_size + buffer.len()] + .copy_from_slice(buffer); + Ok(Some(block_size)) } } + fn main() -> anyhow::Result<()> { redox_daemon::Daemon::new(move |daemon| { - let socket_fd = Socket::create("disk.live").expect("failed to open scheme"); - let mut scheme = DiskScheme::new().unwrap_or_else(|err| { - eprintln!("failed to initialize livedisk scheme: {}", err); - std::process::exit(1) - }); + let event_queue = event::EventQueue::new().unwrap(); + + event::user_data! { + enum Event { + Scheme, + } + }; + + let mut scheme = DiskScheme::new( + "disk.live".to_owned(), + BTreeMap::from([( + 0, + LiveDisk::new().unwrap_or_else(|err| { + eprintln!("failed to initialize livedisk scheme: {}", err); + std::process::exit(1) + }), + )]), + ); + + libredox::call::setrens(0, 0).expect("nvmed: failed to enter null namespace"); + + event_queue + .subscribe( + scheme.event_handle().raw(), + Event::Scheme, + event::EventFlags::READ, + ) + .unwrap(); + daemon.ready().expect("failed to signal readiness"); - loop { - let req = match socket_fd - .next_request(SignalBehavior::Restart) - .expect("failed to get next request") - { - Some(r) => { - if let RequestKind::Call(c) = r.kind() { - c - } else { - continue; - } - } - None => break, - }; - let resp = req.handle_scheme(&mut scheme); - socket_fd - .write_response(resp, SignalBehavior::Restart) - .expect("failed to write packet"); + for event in event_queue { + match event.unwrap().user_data { + Event::Scheme => scheme.tick().unwrap(), + } } std::process::exit(0);