diff --git a/Cargo.lock b/Cargo.lock index da5612e345..e52c374963 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -475,9 +475,10 @@ dependencies = [ name = "ipcd" version = "0.1.0" dependencies = [ + "anyhow", "libredox", "redox-daemon", - "redox-scheme 0.2.4", + "redox-scheme 0.7.0", "redox_event", "redox_syscall", ] @@ -874,6 +875,16 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "redox-scheme" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4da6a0251965958189cdfd5ebb66f99754db4aa165394300aa2b958525d94b64" +dependencies = [ + "libredox", + "redox_syscall", +] + [[package]] name = "redox_event" version = "0.4.1" @@ -902,9 +913,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ "bitflags 2.9.0", ] diff --git a/ipcd/Cargo.toml b/ipcd/Cargo.toml index 89199359fa..3637b17368 100644 --- a/ipcd/Cargo.toml +++ b/ipcd/Cargo.toml @@ -7,5 +7,6 @@ version = "0.1.0" libredox = "0.1.3" redox-daemon = "0.1.2" redox_syscall = "0.5" -redox-scheme = "0.2.1" +redox-scheme = "0.7.0" redox_event = "0.4.0" +anyhow = "1.0.97" diff --git a/ipcd/src/chan.rs b/ipcd/src/chan.rs index 087bbca90a..59462b221a 100644 --- a/ipcd/src/chan.rs +++ b/ipcd/src/chan.rs @@ -1,24 +1,24 @@ +use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult, Response, SignalBehavior, Socket}; use std::{ cmp, collections::{HashMap, VecDeque}, }; -use syscall::{flag::*, error::*, Error}; -use redox_scheme::{SchemeBlockMut, V2}; +use syscall::{error::*, flag::*, schemev2::NewFdFlags, Error}; #[derive(Debug, Default)] pub struct Client { buffer: Vec, - remote: Connection + remote: Connection, } #[derive(Debug, Default)] pub struct Listener { path: Option, - awaiting: VecDeque + awaiting: VecDeque, } #[derive(Debug)] pub enum Extra { Client(Client), - Listener(Listener) + Listener(Listener), } impl Default for Extra { fn default() -> Self { @@ -29,7 +29,7 @@ impl Default for Extra { pub enum Connection { Waiting, Open(usize), - Closed + Closed, } impl Default for Connection { fn default() -> Self { @@ -66,8 +66,8 @@ impl Handle { Extra::Listener(ref mut listener) => { listener.awaiting.push_back(other); Ok(()) - }, - _ => Err(Error::new(EBADF)) + } + _ => Err(Error::new(EBADF)), } } @@ -75,7 +75,7 @@ impl Handle { pub fn require_listener(&mut self) -> Result<&mut Listener> { match self.extra { Extra::Listener(ref mut listener) => Ok(listener), - _ => Err(Error::new(EBADF)) + _ => Err(Error::new(EBADF)), } } @@ -83,36 +83,48 @@ impl Handle { pub fn require_client(&mut self) -> Result<&mut Client> { match self.extra { Extra::Client(ref mut client) => Ok(client), - _ => Err(Error::new(EBADF)) + _ => Err(Error::new(EBADF)), } } } -pub struct ChanScheme { +pub struct ChanScheme<'sock> { handles: HashMap, listeners: HashMap, next_id: usize, - pub socket: redox_scheme::Socket, + socket: &'sock Socket, } -impl ChanScheme { - pub fn new() -> Result { - Ok(Self { +impl<'sock> ChanScheme<'sock> { + pub fn new(socket: &'sock Socket) -> Self { + Self { handles: HashMap::new(), listeners: HashMap::new(), next_id: 0, - socket: redox_scheme::Socket::::nonblock("chan")?, - }) + socket, + } + } + + fn post_fevent(&self, id: usize, flags: usize) -> Result<()> { + let fevent_response = Response::post_fevent(id, flags); + match self + .socket + .write_response(fevent_response, SignalBehavior::Restart) + { + Ok(true) => Ok(()), // Write response success + Ok(false) => Err(Error::new(EAGAIN)), // Write response failed, retry. + Err(err) => Err(err), // Error writing response + } } } -impl SchemeBlockMut for ChanScheme { +impl<'sock> SchemeSync for ChanScheme<'sock> { // ___ ____ _____ _ _ // / _ \| _ \| ____| \ | | // | | | | |_) | _| | \| | // | |_| | __/| |___| |\ | // \___/|_| |_____|_| \_| - fn open(&mut self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result> { + fn open(&mut self, path: &str, flags: usize, _ctx: &CallerCtx) -> Result { let new_id = self.next_id; let mut new = Handle::default(); new.flags = flags; @@ -132,20 +144,27 @@ impl SchemeBlockMut for ChanScheme { // Connect to existing if: O_CREAT isn't set or it already exists // and O_EXCL isn't set let listener_id = *self.listeners.get(path).ok_or(Error::new(ENOENT))?; - let listener = self.handles.get_mut(&listener_id).expect("orphan listener left over"); + let listener = self + .handles + .get_mut(&listener_id) + .expect("orphan listener left over"); listener.connect(new_id)?; // smoltcp sends writeable whenever a listener gets a // client, we'll do the same too (but also readable, why // not) - self.socket.post_fevent(listener_id, (EVENT_READ | EVENT_WRITE).bits())?; + self.post_fevent(listener_id, (EVENT_READ | EVENT_WRITE).bits())?; } self.handles.insert(new_id, new); self.next_id += 1; - Ok(Some(new_id)) + + Ok(OpenResult::ThisScheme { + number: new_id, + flags: NewFdFlags::empty(), + }) } - fn dup(&mut self, id: usize, buf: &[u8]) -> Result> { + fn dup(&mut self, id: usize, buf: &[u8], ctx: &CallerCtx) -> Result { match buf { b"listen" => { loop { @@ -162,28 +181,34 @@ impl SchemeBlockMut for ChanScheme { // mutal. let remote = match self.handles.get_mut(&remote_id) { Some(client) => client, - None => continue // Check next client + None => continue, // Check next client }; match remote.extra { Extra::Client(ref mut client) => { client.remote = Connection::Open(new_id); - }, - Extra::Listener(_) => panic!("newly created handle can't possibly be a listener") + } + Extra::Listener(_) => { + panic!("newly created handle can't possibly be a listener") + } } - self.socket.post_fevent(remote_id, EVENT_WRITE.bits())?; + self.post_fevent(remote_id, EVENT_WRITE.bits())?; new.path = listener_path; self.handles.insert(new_id, new); self.next_id += 1; - Ok(Some(new_id)) + + Ok(OpenResult::ThisScheme { + number: new_id, + flags: NewFdFlags::empty(), + }) } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - Err(Error::new(EAGAIN)) + Ok(OpenResult::WouldBlock) } else { - Ok(None) + Err(Error::new(EWOULDBLOCK)) }; } - }, + } b"connect" => { let new_id = self.next_id; let new = Handle::default(); @@ -195,12 +220,16 @@ impl SchemeBlockMut for ChanScheme { // smoltcp sends writeable whenever a listener gets a // client, we'll do the same too (but also readable, // why not) - self.socket.post_fevent(id, (EVENT_READ | EVENT_WRITE).bits())?; + self.post_fevent(id, (EVENT_READ | EVENT_WRITE).bits())?; self.handles.insert(new_id, new); self.next_id += 1; - Ok(Some(new_id)) - }, + + Ok(OpenResult::ThisScheme { + number: new_id, + flags: NewFdFlags::empty(), + }) + } _ => { // If a buf is provided, different than "connect" / "listen", // turn the socket into a named socket. @@ -217,7 +246,7 @@ impl SchemeBlockMut for ChanScheme { } let flags = handle.flags; - return self.open(path, flags, 0, 0); + return self.open(path, flags, ctx); } } } @@ -228,7 +257,14 @@ impl SchemeBlockMut for ChanScheme { // | | |_| | | (_> < | |___| |__| |_| |___) | |___ // |___\___/ \___/\/ \____|_____\___/|____/|_____| - fn write(&mut self, id: usize, buf: &[u8], _offset: u64, flags: u32) -> Result> { + fn write( + &mut self, + id: usize, + buf: &[u8], + _offset: u64, + flags: u32, + _ctx: &CallerCtx, + ) -> Result { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; let client = handle.require_client()?; @@ -240,27 +276,29 @@ impl SchemeBlockMut for ChanScheme { if client.buffer.len() == buf.len() { // Send readable only if it wasn't readable // before - self.socket.post_fevent(remote_id, EVENT_READ.bits())?; + self.post_fevent(remote_id, EVENT_READ.bits())?; } - Ok(Some(buf.len())) - }, - Extra::Listener(_) => panic!("somehow, a client was connected to a listener directly") + Ok(buf.len()) + } + Extra::Listener(_) => { + panic!("somehow, a client was connected to a listener directly") + } } } else if client.remote == Connection::Closed { Err(Error::new(EPIPE)) } else if (flags as usize) & O_NONBLOCK == O_NONBLOCK { Err(Error::new(EAGAIN)) } else { - Ok(None) + Err(Error::new(EWOULDBLOCK)) } } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result> { + fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { // Write scheme name const PREFIX: &[u8] = b"chan:"; let len = cmp::min(PREFIX.len(), buf.len()); buf[..len].copy_from_slice(&PREFIX[..len]); if len < PREFIX.len() { - return Ok(Some(len)); + return Ok(len); } // Write path @@ -269,14 +307,19 @@ impl SchemeBlockMut for ChanScheme { let len = cmp::min(path.len(), buf.len() - PREFIX.len()); buf[PREFIX.len()..][..len].copy_from_slice(&path.as_bytes()[..len]); - Ok(Some(PREFIX.len() + len)) + Ok(PREFIX.len() + len) } - fn fsync(&mut self, id: usize) -> Result> { - self.handles.get(&id) - .ok_or(Error::new(EBADF)) - .and(Ok(Some(id))) + fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { + self.handles.get(&id).ok_or(Error::new(EBADF)).and(Ok(())) } - fn read(&mut self, id: usize, buf: &mut [u8], _offset: u64, flags: u32) -> Result> { + fn read( + &mut self, + id: usize, + buf: &mut [u8], + _offset: u64, + flags: u32, + _ctx: &CallerCtx, + ) -> Result { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; let client = handle.require_client()?; @@ -284,61 +327,66 @@ impl SchemeBlockMut for ChanScheme { let len = cmp::min(buf.len(), client.buffer.len()); buf[..len].copy_from_slice(&client.buffer[..len]); client.buffer.drain(..len); - Ok(Some(len)) + Ok(len) } else if client.remote == Connection::Closed { // Remote dropped, send EOF - Ok(Some(0)) + Ok(0) } else if (flags as usize) & O_NONBLOCK == O_NONBLOCK { Err(Error::new(EAGAIN)) } else { - Ok(None) + Err(Error::new(EWOULDBLOCK)) } } - fn close(&mut self, id: usize) -> Result> { - let handle = self.handles.remove(&id).ok_or(Error::new(EBADF))?; + fn on_close(&mut self, id: usize) { + let handle = self + .handles + .remove(&id) + .expect("handle pointing to nothing"); match handle.extra { - Extra::Client(client) => if let Connection::Open(remote_id) = client.remote { - let remote = self.handles.get_mut(&remote_id).unwrap(); + Extra::Client(client) => { + if let Connection::Open(remote_id) = client.remote { + let remote = self.handles.get_mut(&remote_id).unwrap(); - match remote.extra { - Extra::Client(ref mut client) => { - client.remote = Connection::Closed; - if client.buffer.is_empty() { - // Post readable on EOF only if it wasn't - // readable before - self.socket.post_fevent(remote_id, EVENT_READ.bits())?; + match remote.extra { + Extra::Client(ref mut client) => { + client.remote = Connection::Closed; + if client.buffer.is_empty() { + // Post readable on EOF only if it wasn't + // readable before + self.post_fevent(remote_id, EVENT_READ.bits()).unwrap(); + } } - }, - Extra::Listener(_) => panic!("a client can't be connected to a listener!") + Extra::Listener(_) => panic!("a client can't be connected to a listener!"), + } + } + } + Extra::Listener(listener) => { + if let Some(path) = listener.path { + self.listeners.remove(&path); } - }, - Extra::Listener(listener) => if let Some(path) = listener.path { - self.listeners.remove(&path); } } - Ok(Some(0)) } - // ____ _ ____ _ __ __ _____ _____ _____ ____ ____ // | _ \ / \ | _ \ / \ | \/ | ____|_ _| ____| _ \/ ___| // | |_) / _ \ | |_) | / _ \ | |\/| | _| | | | _| | |_) \___ \ // | __/ ___ \| _ < / ___ \| | | | |___ | | | |___| _ < ___) | // |_| /_/ \_\_| \_\/_/ \_\_| |_|_____| |_| |_____|_| \_\____/ - fn fcntl(&mut self, id: usize, cmd: usize, arg: usize) -> Result> { + fn fcntl(&mut self, id: usize, cmd: usize, arg: usize, _ctx: &CallerCtx) -> Result { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; match cmd { - F_GETFL => Ok(Some(handle.flags)), + F_GETFL => Ok(handle.flags), F_SETFL => { handle.flags = arg; - Ok(Some(0)) - }, - _ => Err(Error::new(EINVAL)) + Ok(0) + } + _ => Err(Error::new(EINVAL)), } } - fn fevent(&mut self, id: usize, _flags: EventFlags) -> Result> { + fn fevent(&mut self, id: usize, _flags: EventFlags, _ctx: &CallerCtx) -> Result { let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; let mut events = EventFlags::empty(); match handle.extra { @@ -349,11 +397,13 @@ impl SchemeBlockMut for ChanScheme { if !client.buffer.is_empty() || client.remote == Connection::Closed { events |= EVENT_READ; } - }, - Extra::Listener(ref listener) => if !listener.awaiting.is_empty() { - events |= EVENT_READ | EVENT_WRITE; + } + Extra::Listener(ref listener) => { + if !listener.awaiting.is_empty() { + events |= EVENT_READ | EVENT_WRITE; + } } } - Ok(Some(events)) + Ok(events) } } diff --git a/ipcd/src/main.rs b/ipcd/src/main.rs index 710a784439..8aaf664fd2 100644 --- a/ipcd/src/main.rs +++ b/ipcd/src/main.rs @@ -1,9 +1,8 @@ #![feature(int_roundings, let_chains)] -use std::collections::VecDeque; -use event::{EventQueue, EventFlags}; -use redox_scheme::{CallRequest, RequestKind, Response, SignalBehavior}; -use syscall::{Error, Result, EAGAIN, EWOULDBLOCK, ENODEV, EINTR}; +use event::{EventFlags, EventQueue}; +use redox_scheme::{wrappers::ReadinessBased, Socket}; +use std::sync::Mutex; mod chan; mod shm; @@ -21,138 +20,126 @@ fn main() { std::process::exit(1); } } - }).expect("ipcd: failed to daemonize"); + }) + .expect("ipcd: failed to daemonize"); } -fn inner(daemon: redox_daemon::Daemon) -> Result<()> { +fn inner(daemon: redox_daemon::Daemon) -> anyhow::Result<()> { event::user_data! { enum EventSource { ChanSocket, ShmSocket, } } - let chan = ChanScheme::new()?; - let shm = ShmScheme::new()?; + + // Prepare chan scheme + let chan_socket = Socket::nonblock("chan") + .map_err(|e| anyhow::anyhow!("failed to create chan scheme: {e}"))?; + let chan = Mutex::new(ChanScheme::new(&chan_socket)); + let mut chan_handler = ReadinessBased::new(&chan_socket, 16); + + // Prepare shm scheme + let shm_socket = + Socket::nonblock("shm").map_err(|e| anyhow::anyhow!("failed to create shm socket: {e}"))?; + let shm = Mutex::new(ShmScheme::new()); + let mut shm_handler = ReadinessBased::new(&shm_socket, 16); + daemon.ready().unwrap(); // Create event listener for both files - let mut event_queue = EventQueue::::new()?; - - event_queue.subscribe(chan.socket.inner().raw(), EventSource::ChanSocket, EventFlags::READ)?; - event_queue.subscribe(shm.socket.inner().raw(), EventSource::ShmSocket, EventFlags::READ)?; - - struct Todo { - req: Option, - canceling: bool, - } - let mut todo = VecDeque::::with_capacity(16); + let mut event_queue = EventQueue::::new() + .map_err(|e| anyhow::anyhow!("failed to create event queue: {e}"))?; + event_queue + .subscribe( + chan_socket.inner().raw(), + EventSource::ChanSocket, + EventFlags::READ, + ) + .map_err(|e| anyhow::anyhow!("failed to subscribe chan socket: {e}"))?; + event_queue + .subscribe( + shm_socket.inner().raw(), + EventSource::ShmSocket, + EventFlags::READ, + ) + .map_err(|e| anyhow::anyhow!("failed to subscribe shm socket: {e}"))?; libredox::call::setrens(0, 0)?; - let mut chan_opt = Some(chan); - let mut shm_opt = Some(shm); - while chan_opt.is_some() || shm_opt.is_some() { + // EOF flags + let mut chan_eof = false; + let mut shm_eof = false; + while !(chan_eof && shm_eof) { let Some(event_res) = event_queue.next() else { break; }; - let event = event_res?; + let event = event_res.map_err(|e| anyhow::anyhow!("error occured in event queue: {e}"))?; match event.user_data { EventSource::ChanSocket => { - let mut error: Option = None; - - let unmount = if let Some(ref mut chan) = chan_opt { - let eof = loop { - match chan.socket.next_request(SignalBehavior::Restart) { - Ok(None) => break true, - Ok(Some(request)) => match request.kind() { - RequestKind::Call(request) => todo.push_front(Todo { req: Some(request), canceling: false }), - RequestKind::Cancellation(request) => { - if let Some(affected_packet) = todo.iter_mut().find(|t| t.req.as_ref().map_or(false, |r| r.request().request_id() == request.id)) { - affected_packet.canceling = true; - } - } - _ => (), - } - Err(Error { errno: EAGAIN | EWOULDBLOCK }) => break false, - Err(error) => return Err(error), - } - }; - - // Process queue, delete finished items - todo.retain_mut(|slot| { - let req = slot.req.take().unwrap(); - - match req.handle_scheme_block_mut(chan) { - Some(res) => { - if let Err(err) = chan.socket.write_response(res, SignalBehavior::Restart) { - error = Some(err); - } - false - } - None if slot.canceling => { - if let Err(err) = chan.socket.write_response(Response::new(&req, Err(Error::new(EINTR))), SignalBehavior::Restart) { - error = Some(err); - } - false - } - None => { - slot.req = Some(req); - true - } - } - }); - - eof - } else { - false - }; - - if unmount && let Some(chan) = chan_opt.take() { - for slot in todo.drain(..) { - let res = if slot.canceling { - Err(Error::new(EINTR)) - } else { - Err(Error::new(ENODEV)) - }; - if let Err(err) = chan.socket.write_response(Response::new(&slot.req.unwrap(), res), SignalBehavior::Restart) { - error = Some(err); + // Channel scheme + if !chan_eof { + // 1. Read requests + match chan_handler.read_requests() { + Ok(true) => {} // Read requests success + Ok(false) => { + // EOF + chan_eof = true; } + Err(err) => return Err(anyhow::anyhow!("{err}")), } } - if let Some(err) = error { - return Err(err); + // 2. Process requests + chan_handler.process_requests(|| chan.lock().unwrap()); + + // 3.Poll all blocking requests + chan_handler + .poll_all_requests(|| chan.lock().unwrap()) + .map_err(|e| anyhow::anyhow!("error occured in poll_all_requests: {e}"))?; + + // 3. Write responses + // write_responses returns a Result, but currently only returns true. + match chan_handler.write_responses() { + Ok(true) => {} // Read requests success + Ok(false) => { + // EOF + chan_eof = true; + } + Err(err) => return Err(anyhow::anyhow!("{err}")), } - }, + } EventSource::ShmSocket => { - let unmount = if let Some(ref mut shm) = shm_opt { - let eof = loop { - match shm.socket.next_request(SignalBehavior::Restart) { - Ok(None) => break true, - Ok(Some(request)) => match request.kind() { - RequestKind::Call(request) => { - let response = request.handle_scheme_mut(shm); - shm.socket.write_response(response, SignalBehavior::Restart)?; - } - _ => (), - }, - Err(Error { errno: EAGAIN | EWOULDBLOCK }) => break false, - Err(err) => return Err(err), - }; - }; + // Shared memory scheme + if !shm_eof { + // 1. Read requests + match shm_handler.read_requests() { + Ok(true) => {} // Read requests success + Ok(false) => { + // EOF + shm_eof = true; + } + Err(err) => return Err(anyhow::anyhow!("{err}")), + } + } - eof - } else { - false - }; + // 2. Process requests + shm_handler.process_requests(|| shm.lock().unwrap()); - if unmount { - shm_opt.take(); + // shm is not a blocking scheme + + // 3. Write responses + // write_responses returns a Result, but currently only returns true. + match shm_handler.write_responses() { + Ok(true) => {} // Read requests success + Ok(false) => { + // EOF + shm_eof = true; + } + Err(err) => return Err(anyhow::anyhow!("{err}")), } } } } - Ok(()) } diff --git a/ipcd/src/shm.rs b/ipcd/src/shm.rs index ac2b87ff0b..b1e16ed996 100644 --- a/ipcd/src/shm.rs +++ b/ipcd/src/shm.rs @@ -1,45 +1,51 @@ +use redox_scheme::{scheme::SchemeSync, CallerCtx, OpenResult}; use std::{ cmp, - collections::{HashMap, hash_map::Entry}, + collections::{hash_map::Entry, HashMap}, rc::Rc, }; -use syscall::{error::*, Error, Map, Result, MapFlags, PAGE_SIZE, MAP_PRIVATE}; -use redox_scheme::{SchemeMut, V2}; +use syscall::{ + error::*, schemev2::NewFdFlags, Error, Map, MapFlags, Result, MAP_PRIVATE, PAGE_SIZE, +}; #[derive(Default)] pub struct ShmHandle { buffer: Option, - refs: usize + refs: usize, } pub struct ShmScheme { maps: HashMap, ShmHandle>, handles: HashMap>, next_id: usize, - pub socket: redox_scheme::Socket, } impl ShmScheme { - pub fn new() -> Result { - Ok(Self { + pub fn new() -> Self { + Self { maps: HashMap::new(), handles: HashMap::new(), next_id: 0, - socket: redox_scheme::Socket::::nonblock("shm")?, - }) + } } } -impl SchemeMut for ShmScheme { - fn open(&mut self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { +impl SchemeSync for ShmScheme { + fn open(&mut self, path: &str, _flags: usize, _ctx: &CallerCtx) -> Result { let path = Rc::from(path); - let entry = self.maps.entry(Rc::clone(&path)).or_insert(ShmHandle::default()); + let entry = self + .maps + .entry(Rc::clone(&path)) + .or_insert(ShmHandle::default()); entry.refs += 1; self.handles.insert(self.next_id, path); let id = self.next_id; self.next_id += 1; - Ok(id) + Ok(OpenResult::ThisScheme { + number: id, + flags: NewFdFlags::empty(), + }) } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { + fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { // Write scheme name const PREFIX: &[u8] = b"shm:"; let len = cmp::min(PREFIX.len(), buf.len()); @@ -55,29 +61,40 @@ impl SchemeMut for ShmScheme { Ok(PREFIX.len() + len) } - fn close(&mut self, id: usize) -> Result { - let path = self.handles.remove(&id).ok_or(Error::new(EBADF))?; + fn on_close(&mut self, id: usize) { + let path = self.handles.remove(&id).unwrap(); let mut entry = match self.maps.entry(path) { Entry::Occupied(entry) => entry, - Entry::Vacant(_) => panic!("handle pointing to nothing") + Entry::Vacant(_) => panic!("handle pointing to nothing"), }; entry.get_mut().refs -= 1; if entry.get().refs == 0 { // There is no other reference to this entry, drop entry.remove_entry(); } - Ok(0) } - fn mmap_prep(&mut self, id: usize, offset: u64, size: usize, _: MapFlags) -> Result { + fn mmap_prep( + &mut self, + id: usize, + offset: u64, + size: usize, + _flags: MapFlags, + _ctx: &CallerCtx, + ) -> Result { let path = self.handles.get(&id).ok_or(Error::new(EBADF))?; let total_size = offset as usize + size; - match self.maps.get_mut(path).expect("handle pointing to nothing").buffer { + match self + .maps + .get_mut(path) + .expect("handle pointing to nothing") + .buffer + { Some(ref mut buf) => { if total_size > buf.len() { return Err(Error::new(ERANGE)); } Ok(buf.as_ptr() + offset as usize) - }, + } ref mut buf @ None => { *buf = Some(MmapGuard::alloc(size.div_ceil(PAGE_SIZE))?); Ok(buf.as_mut().unwrap().as_ptr() + offset as usize) @@ -93,12 +110,19 @@ pub struct MmapGuard { impl MmapGuard { pub fn alloc(page_count: usize) -> Result { let size = page_count * PAGE_SIZE; - let base = unsafe { syscall::fmap(!0, &Map { offset: 0, size, flags: MAP_PRIVATE, address: 0 }) }?; + let base = unsafe { + syscall::fmap( + !0, + &Map { + offset: 0, + size, + flags: MAP_PRIVATE, + address: 0, + }, + ) + }?; - Ok(Self { - base, - size, - }) + Ok(Self { base, size }) } pub fn len(&self) -> usize { self.size