diff --git a/Cargo.lock b/Cargo.lock index 7c4b35cb71..44fde5ca6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -591,6 +591,8 @@ dependencies = [ "pcid", "redox-daemon", "redox-log", + "redox-scheme", + "redox_event", "redox_syscall 0.5.2", ] diff --git a/storage/ided/Cargo.toml b/storage/ided/Cargo.toml index 2303be020b..e590d22e97 100644 --- a/storage/ided/Cargo.toml +++ b/storage/ided/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "ided" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] common = { path = "../../common" } @@ -11,4 +11,6 @@ log = "0.4" pcid = { path = "../../pcid" } redox-daemon = "0.1" redox-log = "0.1" -redox_syscall = "0.5" +redox_syscall = { version = "0.5", features = ["std"] } +redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } +redox_event = "0.4" diff --git a/storage/ided/src/main.rs b/storage/ided/src/main.rs index decfacd9bc..0a10a625a0 100644 --- a/storage/ided/src/main.rs +++ b/storage/ided/src/main.rs @@ -1,8 +1,10 @@ use driver_block::Disk; +use event::{EventFlags, RawEventQueue}; use libredox::flag; use log::{error, info}; use pcid_interface::{PciBar, PcidServerHandle}; use redox_log::{OutputBuilder, RedoxLogger}; +use redox_scheme::{RequestKind, Response, SignalBehavior, Socket, V2}; use std::{ fs::File, io::{ErrorKind, Read, Write}, @@ -12,11 +14,7 @@ use std::{ time::Duration, }; use syscall::{ - data::{Event, Packet}, - error::{Error, ENODEV}, - flag::{EVENT_READ}, - io::Io, - scheme::SchemeBlockMut, + data::{Event, Packet}, error::{Error, ENODEV}, flag::EVENT_READ, io::Io, scheme::SchemeBlockMut, EAGAIN, EINTR, EWOULDBLOCK }; use crate::{ @@ -236,12 +234,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { } let scheme_name = format!("disk.{}", name); - let socket_fd = libredox::call::open( - &format!(":{}", scheme_name), - flag::O_RDWR | flag::O_CREAT | flag::O_NONBLOCK, - 0, - ).expect("ided: failed to create disk scheme"); - let mut socket = unsafe { File::from_raw_fd(socket_fd as RawFd) }; + let socket_fd = Socket::::nonblock(&scheme_name) + .expect("ided: failed to create disk scheme"); let primary_irq_fd = libredox::call::open( &format!("irq:{}", primary_irq), @@ -257,63 +251,59 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { ).expect("ided: failed to open irq file"); let mut secondary_irq_file = unsafe { File::from_raw_fd(secondary_irq_fd as RawFd) }; - let mut event_file = File::open("event:").expect("ided: failed to open event file"); + let mut event_queue = RawEventQueue::new().expect("ided: failed to open event file"); libredox::call::setrens(0, 0).expect("ided: failed to enter null namespace"); daemon.ready().expect("ided: failed to notify parent"); - event_file.write(&Event { - id: socket_fd, - flags: EVENT_READ, - data: 0 - }).expect("ided: failed to event disk scheme"); + event_queue.subscribe( + socket_fd.inner().raw(), + 0, + EventFlags::READ, + ).expect("ided: failed to event disk scheme"); - event_file.write(&Event { - id: primary_irq_fd, - flags: EVENT_READ, - data: 0 - }).expect("ided: failed to event irq scheme"); + event_queue.subscribe( + primary_irq_fd, + 0, + EventFlags::READ, + ).expect("ided: failed to event irq scheme"); - event_file.write(&Event { - id: secondary_irq_fd, - flags: EVENT_READ, - data: 0 - }).expect("ided: failed to event irq scheme"); + event_queue.subscribe( + secondary_irq_fd, + 0, + EventFlags::READ, + ).expect("ided: failed to event irq scheme"); let mut scheme = DiskScheme::new(scheme_name, chans, disks); - let mut mounted = true; let mut todo = Vec::new(); - while mounted { - let mut event = Event::default(); - if event_file.read(&mut event).expect("ided: failed to read event file") == 0 { + 'outer: loop { + let Some(event) = event_queue.next().transpose().expect("ided: failed to read event file") else { break; - } - if event.id == socket_fd { + }; + if event.fd == socket_fd.inner().raw() { loop { - let mut packet = Packet::default(); - match socket.read(&mut packet) { - Ok(0) => { - mounted = false; - break; + let req = match socket_fd.next_request(SignalBehavior::Interrupt) { + Ok(None) => break 'outer, + Ok(Some(r)) => if let RequestKind::Call(c) = r.kind() { + c + } else { + continue; }, - Ok(_) => (), - Err(err) => if err.kind() == ErrorKind::WouldBlock { + Err(err) => if matches!(err.errno, EAGAIN | EWOULDBLOCK | EINTR) { break; } else { panic!("ided: failed to read disk scheme: {}", err); } - } - - if let Some(a) = scheme.handle(&packet) { - packet.a = a; - socket.write(&mut packet).expect("ided: failed to write disk scheme"); + }; + if let Some(resp) = req.handle_scheme_block_mut(&mut scheme) { + socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme"); } else { - todo.push(packet); + todo.push(req); } } - } else if event.id == primary_irq_fd { + } else if event.fd == primary_irq_fd { let mut irq = [0; 8]; if primary_irq_file.read(&mut irq).expect("ided: failed to read irq file") >= irq.len() { if scheme.irq(0) { @@ -322,17 +312,15 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { // Handle todos in order to finish previous packets if possible let mut i = 0; while i < todo.len() { - if let Some(a) = scheme.handle(&todo[i]) { - let mut packet = todo.remove(i); - packet.a = a; - socket.write(&mut packet).expect("ided: failed to write disk scheme"); + if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) { + socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme"); } else { i += 1; } } } } - } else if event.id == secondary_irq_fd { + } else if event.fd == secondary_irq_fd { let mut irq = [0; 8]; if secondary_irq_file.read(&mut irq).expect("ided: failed to read irq file") >= irq.len() { if scheme.irq(1) { @@ -341,10 +329,8 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { // Handle todos in order to finish previous packets if possible let mut i = 0; while i < todo.len() { - if let Some(a) = scheme.handle(&todo[i]) { - let mut packet = todo.remove(i); - packet.a = a; - socket.write(&mut packet).expect("ided: failed to write disk scheme"); + if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) { + socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme"); } else { i += 1; } @@ -352,26 +338,22 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { } } } else { - error!("Unknown event {}", event.id); + error!("Unknown event {}", event.fd); } // Handle todos to start new packets if possible let mut i = 0; while i < todo.len() { - if let Some(a) = scheme.handle(&todo[i]) { - let mut packet = todo.remove(i); - packet.a = a; - socket.write(&packet).expect("ided: failed to write disk scheme"); + if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) { + socket_fd.write_response(resp, SignalBehavior::Restart).expect("ided: failed to write disk scheme"); } else { i += 1; } } - if ! mounted { - for mut packet in todo.drain(..) { - packet.a = Error::mux(Err(Error::new(ENODEV))); - socket.write(&packet).expect("ided: failed to write disk scheme"); - } + for req in todo.drain(..) { + socket_fd.write_response(Response::new(&req, Err(Error::new(ENODEV))), SignalBehavior::Restart) + .expect("ided: failed to write disk scheme"); } } diff --git a/storage/ided/src/scheme.rs b/storage/ided/src/scheme.rs index 31032d4a9a..bb46d11082 100644 --- a/storage/ided/src/scheme.rs +++ b/storage/ided/src/scheme.rs @@ -1,23 +1,23 @@ use std::collections::BTreeMap; -use std::{cmp, str}; -use std::convert::{TryFrom}; +use std::str; use std::fmt::Write; -use std::io::prelude::*; use std::sync::{Arc, Mutex}; use driver_block::{Disk, DiskWrapper}; +use syscall::schemev2::NewFdFlags; use syscall::{ - Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, - Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, - O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; + Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Stat, MODE_DIR, + MODE_FILE, O_DIRECTORY, O_STAT, +}; +use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut}; use crate::ide::Channel; #[derive(Clone)] enum Handle { - List(Vec, usize), // Dir contents buffer, position - Disk(usize, usize), // Disk index, position - Partition(usize, u32, usize), // Disk index, partition index, position + List(Vec), // Dir contents buffer + Disk(usize), // Disk index + Partition(usize, u32), // Disk index, partition index } pub struct DiskScheme { @@ -31,7 +31,7 @@ pub struct DiskScheme { impl DiskScheme { pub fn new(scheme_name: String, chans: Vec>>, disks: Vec>) -> DiskScheme { DiskScheme { - scheme_name: scheme_name, + scheme_name, chans: chans.into_boxed_slice(), disks: disks.into_iter().map(DiskWrapper::new).collect::>().into_boxed_slice(), handles: BTreeMap::new(), @@ -40,7 +40,7 @@ impl DiskScheme { } pub fn irq(&mut self, chan_i: usize) -> bool { - let mut chan = self.chans[chan_i].lock().unwrap(); + let _chan = self.chans[chan_i].lock().unwrap(); //TODO: check chan for irq true } @@ -49,10 +49,10 @@ impl DiskScheme { fn check_locks(&self, disk_i: usize, part_i_opt: Option) -> Result<()> { for (_, handle) in self.handles.iter() { match handle { - Handle::Disk(i, _) => if disk_i == *i { + Handle::Disk(i) => if disk_i == *i { return Err(Error::new(ENOLCK)); }, - Handle::Partition(i, p, _) => if disk_i == *i { + Handle::Partition(i, p) => if disk_i == *i { match part_i_opt { Some(part_i) => if part_i == *p { return Err(Error::new(ENOLCK)); @@ -70,8 +70,8 @@ impl DiskScheme { } impl SchemeBlockMut for DiskScheme { - fn open(&mut self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result> { - if uid == 0 { + fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result> { + if ctx.uid == 0 { let path_str = path.trim_matches('/'); if path_str.is_empty() { if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT { @@ -90,8 +90,8 @@ impl SchemeBlockMut for DiskScheme { let id = self.next_id; self.next_id += 1; - self.handles.insert(id, Handle::List(list.into_bytes(), 0)); - Ok(Some(id)) + self.handles.insert(id, Handle::List(list.into_bytes())); + Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED })) } else { Err(Error::new(EISDIR)) } @@ -113,8 +113,8 @@ impl SchemeBlockMut for DiskScheme { let id = self.next_id; self.next_id += 1; - self.handles.insert(id, Handle::Partition(i, p, 0)); - Ok(Some(id)) + self.handles.insert(id, Handle::Partition(i, p)); + Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED })) } else { Err(Error::new(ENOENT)) } @@ -126,8 +126,8 @@ impl SchemeBlockMut for DiskScheme { let id = self.next_id; self.next_id += 1; - self.handles.insert(id, Handle::Disk(i, 0)); - Ok(Some(id)) + self.handles.insert(id, Handle::Disk(i)); + Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED })) } else { Err(Error::new(ENOENT)) } @@ -155,19 +155,19 @@ impl SchemeBlockMut for DiskScheme { fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result> { match *self.handles.get(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref data, _) => { + Handle::List(ref data) => { stat.st_mode = MODE_DIR; stat.st_size = data.len() as u64; Ok(Some(0)) }, - Handle::Disk(number, _) => { + Handle::Disk(number) => { let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?; stat.st_mode = MODE_FILE; stat.st_size = disk.size(); stat.st_blksize = disk.block_length()?; Ok(Some(0)) } - Handle::Partition(disk_id, part_num, _) => { + Handle::Partition(disk_id, part_num) => { let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?; let size = { let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?; @@ -203,8 +203,8 @@ impl SchemeBlockMut for DiskScheme { } match *handle { - Handle::List(_, _) => (), - Handle::Disk(number, _) => { + Handle::List(_) => (), + Handle::Disk(number) => { let number_str = format!("{}", number); let number_bytes = number_str.as_bytes(); j = 0; @@ -214,7 +214,7 @@ impl SchemeBlockMut for DiskScheme { j += 1; } } - Handle::Partition(disk_num, part_num, _) => { + Handle::Partition(disk_num, part_num) => { let path = format!("{}p{}", disk_num, part_num); let path_bytes = path.as_bytes(); j = 0; @@ -229,29 +229,25 @@ impl SchemeBlockMut for DiskScheme { Ok(Some(i)) } - fn read(&mut self, id: usize, buf: &mut [u8]) -> Result> { + fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _flags: u32) -> Result> { match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref handle, ref mut size) => { - let count = (&handle[*size..]).read(buf).unwrap(); - *size += count; - Ok(Some(count)) + Handle::List(ref handle) => { + let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]); + let bytes = src.len().min(buf.len()); + buf[..bytes].copy_from_slice(&src[..bytes]); + Ok(Some(bytes)) }, - Handle::Disk(number, ref mut size) => { + Handle::Disk(number) => { let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?; let blk_len = disk.block_length()?; - if let Some(count) = disk.read((*size as u64)/(blk_len as u64), buf)? { - *size += count; - Ok(Some(count)) - } else { - Ok(None) - } + disk.read(offset / u64::from(blk_len), buf) } - Handle::Partition(disk_num, part_num, ref mut position) => { + Handle::Partition(disk_num, part_num) => { let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?; let blksize = disk.block_length()?; // validate that we're actually reading within the bounds of the partition - let rel_block = *position as u64 / blksize as u64; + let rel_block = offset / u64::from(blksize); let abs_block = { let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?; @@ -264,36 +260,27 @@ impl SchemeBlockMut for DiskScheme { abs_block }; - if let Some(count) = disk.read(abs_block, buf)? { - Ok(Some(count)) - } else { - Ok(None) - } + disk.read(abs_block, buf) } } } - fn write(&mut self, id: usize, buf: &[u8]) -> Result> { + fn write(&mut self, id: usize, buf: &[u8], offset: u64, _flags: u32) -> Result> { match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(_, _) => { + Handle::List(_) => { Err(Error::new(EBADF)) }, - Handle::Disk(number, ref mut size) => { + Handle::Disk(number) => { let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?; let blk_len = disk.block_length()?; - if let Some(count) = disk.write((*size as u64)/(blk_len as u64), buf)? { - *size += count; - Ok(Some(count)) - } else { - Ok(None) - } + disk.write(offset / u64::from(blk_len), buf) } - Handle::Partition(disk_num, part_num, ref mut position) => { + Handle::Partition(disk_num, part_num) => { let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?; let blksize = disk.block_length()?; // validate that we're actually reading within the bounds of the partition - let rel_block = *position as u64 / blksize as u64; + let rel_block = offset / u64::from(blksize as u64); let abs_block = { let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?; @@ -306,54 +293,24 @@ impl SchemeBlockMut for DiskScheme { abs_block }; - if let Some(count) = disk.write(abs_block, buf)? { - Ok(Some(count)) - } else { - Ok(None) - } + disk.write(abs_block, buf) } } } - fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result> { - let pos = pos as usize; - + fn fsize(&mut self, id: usize) -> Result> { match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { - Handle::List(ref mut handle, ref mut size) => { - let len = handle.len() as usize; - *size = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(Some(*size as isize)) + Handle::List(ref mut handle) => { + Ok(Some(handle.len() as u64)) }, - Handle::Disk(number, ref mut size) => { + Handle::Disk(number) => { let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?; - let len = disk.size() as usize; - *size = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; - - Ok(Some(*size as isize)) + Ok(Some(disk.size())) } - Handle::Partition(disk_num, part_num, ref mut position) => { + Handle::Partition(disk_num, part_num) => { let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?; let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size; - let len = u64::from(disk.block_length()?) * block_count; - - *position = match whence { - SEEK_SET => cmp::min(len as usize, pos) as usize, // Why isn't pos u64? - SEEK_CUR => cmp::max(0, cmp::min(len as isize, *position as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)), - }; - Ok(Some(*position as isize)) + Ok(Some(u64::from(disk.block_length()?) * block_count)) } } }