From d20dd30ccf87380dd085c576ee70cfa42651dbcd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Apr 2025 19:10:49 +0200 Subject: [PATCH 1/3] Move logd to redox-scheme 0.5 --- Cargo.lock | 2 +- logd/Cargo.toml | 2 +- logd/src/main.rs | 17 +++++++------ logd/src/scheme.rs | 60 +++++++++++++++++++++++++++------------------- 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f007c41b2c..e16f7f2693 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -486,7 +486,7 @@ version = "0.1.0" dependencies = [ "libredox 0.1.3", "redox-daemon", - "redox-scheme 0.2.4", + "redox-scheme 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.5.11", ] diff --git a/logd/Cargo.toml b/logd/Cargo.toml index ab9f15e31a..7b60a42f96 100644 --- a/logd/Cargo.toml +++ b/logd/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" redox_syscall = "0.5" redox-daemon = "0.1.2" libredox = "0.1.3" -redox-scheme = "0.2.1" +redox-scheme = "0.5" diff --git a/logd/src/main.rs b/logd/src/main.rs index 11b04c8d41..42604cda11 100644 --- a/logd/src/main.rs +++ b/logd/src/main.rs @@ -1,4 +1,4 @@ -use redox_scheme::{RequestKind, SignalBehavior, Socket, V2}; +use redox_scheme::{RequestKind, SignalBehavior, Socket}; use std::env; use std::fs::OpenOptions; use std::process; @@ -17,7 +17,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { } } - let socket = Socket::::create("log").expect("logd: failed to create log scheme"); + let socket = Socket::create("log").expect("logd: failed to create log scheme"); libredox::call::setrens(0, 0).expect("logd: failed to enter null namespace"); @@ -31,13 +31,16 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { .next_request(SignalBehavior::Restart) .expect("logd: failed to read events from log scheme") { - scheme.current_pid = request.context_id(); - - let RequestKind::Call(request) = request.kind() else { - continue; + let request = match request.kind() { + RequestKind::Call(call) => call, + RequestKind::OnClose { id } => { + scheme.on_close(id); + continue; + } + _ => continue, }; - let response = request.handle_scheme_mut(&mut scheme); + let response = request.handle_sync(&mut scheme); socket .write_responses(&[response], SignalBehavior::Restart) .expect("logd: failed to write responses to log scheme"); diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs index 921fe08c5f..802f02ec94 100644 --- a/logd/src/scheme.rs +++ b/logd/src/scheme.rs @@ -4,8 +4,10 @@ use std::io::Write; use std::mem; use std::sync::mpsc::{self, Sender}; -use redox_scheme::SchemeMut; +use redox_scheme::scheme::SchemeSync; +use redox_scheme::{CallerCtx, OpenResult}; use syscall::error::*; +use syscall::schemev2::NewFdFlags; pub struct LogHandle { context: Box, @@ -16,7 +18,6 @@ pub struct LogScheme { next_id: usize, output_tx: Sender>, handles: BTreeMap, - pub current_pid: usize, } impl LogScheme { @@ -36,13 +37,12 @@ impl LogScheme { next_id: 0, output_tx, handles: BTreeMap::new(), - current_pid: 0, } } } -impl SchemeMut for LogScheme { - fn open(&mut self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result { +impl SchemeSync for LogScheme { + fn open(&mut self, path: &str, _flags: usize, _ctx: &CallerCtx) -> Result { let id = self.next_id; self.next_id += 1; @@ -54,10 +54,20 @@ impl SchemeMut for LogScheme { }, ); - Ok(id) + Ok(OpenResult::ThisScheme { + number: id, + flags: NewFdFlags::empty(), + }) } - 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(&id).ok_or(Error::new(EBADF))?; // TODO @@ -65,13 +75,17 @@ impl SchemeMut for LogScheme { Ok(0) } - 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 handle_buf = handle - .bufs - .entry(self.current_pid) - .or_insert_with(|| Vec::new()); + let handle_buf = handle.bufs.entry(ctx.pid).or_insert_with(|| Vec::new()); let mut i = 0; while i < buf.len() { @@ -94,13 +108,13 @@ impl SchemeMut for LogScheme { Ok(i) } - 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(&id).ok_or(Error::new(EBADF))?; Ok(0) } - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { + fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; let scheme_path = b"log:"; @@ -122,19 +136,17 @@ impl SchemeMut for LogScheme { Ok(i) } - fn fsync(&mut self, id: usize) -> Result { + fn fsync(&mut self, id: usize, _ctx: &CallerCtx) -> Result<()> { let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; //TODO: flush remaining data? - Ok(0) - } - - fn close(&mut self, id: usize) -> Result { - self.handles.remove(&id).ok_or(Error::new(EBADF))?; - - //TODO: flush remaining data? - - Ok(0) + Ok(()) + } +} + +impl LogScheme { + pub fn on_close(&mut self, id: usize) { + self.handles.remove(&id); } } From 034d76ffd58e7e5001528d3677d0a530a8d177eb Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Apr 2025 19:33:49 +0200 Subject: [PATCH 2/3] logd: Add api to add new sink sources at runtime This will allow logd to be started before fbbootlogd. --- logd/src/main.rs | 2 - logd/src/scheme.rs | 95 +++++++++++++++++++++++++++++++++------------- 2 files changed, 69 insertions(+), 28 deletions(-) diff --git a/logd/src/main.rs b/logd/src/main.rs index 42604cda11..5b6e23243c 100644 --- a/logd/src/main.rs +++ b/logd/src/main.rs @@ -19,8 +19,6 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let socket = Socket::create("log").expect("logd: failed to create log scheme"); - libredox::call::setrens(0, 0).expect("logd: failed to enter null namespace"); - eprintln!("logd: ready for logging on log:"); daemon.ready().expect("logd: failed to notify parent"); diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs index 802f02ec94..e10e77c1ad 100644 --- a/logd/src/scheme.rs +++ b/logd/src/scheme.rs @@ -1,7 +1,8 @@ use std::collections::BTreeMap; -use std::fs::File; +use std::fs::{File, OpenOptions}; use std::io::Write; use std::mem; +use std::path::PathBuf; use std::sync::mpsc::{self, Sender}; use redox_scheme::scheme::SchemeSync; @@ -9,26 +10,46 @@ use redox_scheme::{CallerCtx, OpenResult}; use syscall::error::*; use syscall::schemev2::NewFdFlags; -pub struct LogHandle { - context: Box, - bufs: BTreeMap>, +pub enum LogHandle { + Log { + context: Box, + bufs: BTreeMap>, + }, + AddSink, } pub struct LogScheme { next_id: usize, - output_tx: Sender>, + output_tx: Sender, handles: BTreeMap, } +enum OutputCmd { + Log(Vec), + AddSink(PathBuf), +} + impl LogScheme { pub fn new(mut files: Vec) -> Self { - let (output_tx, output_rx) = mpsc::channel::>(); + let (output_tx, output_rx) = mpsc::channel::(); std::thread::spawn(move || { - for line in output_rx { - for file in &mut files { - let _ = file.write(&line); - let _ = file.flush(); + for cmd in output_rx { + match cmd { + OutputCmd::Log(line) => { + for file in &mut files { + let _ = file.write(&line); + let _ = file.flush(); + } + } + OutputCmd::AddSink(sink_path) => { + match OpenOptions::new().write(true).open(&sink_path) { + Ok(file) => files.push(file), + Err(err) => { + eprintln!("logd: failed to open {:?}: {:?}", sink_path, err) + } + } + } } } }); @@ -46,13 +67,17 @@ impl SchemeSync for LogScheme { let id = self.next_id; self.next_id += 1; - self.handles.insert( - id, - LogHandle { - context: path.to_string().into_boxed_str(), - bufs: BTreeMap::new(), - }, - ); + if path == "add_sink" { + self.handles.insert(id, LogHandle::AddSink); + } else { + self.handles.insert( + id, + LogHandle::Log { + context: path.to_string().into_boxed_str(), + bufs: BTreeMap::new(), + }, + ); + } Ok(OpenResult::ThisScheme { number: id, @@ -83,23 +108,38 @@ impl SchemeSync for LogScheme { _flags: u32, ctx: &CallerCtx, ) -> Result { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; + let (context, bufs) = match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? { + LogHandle::Log { context, bufs } => (context, bufs), + LogHandle::AddSink => { + // FIXME maybe check if root - let handle_buf = handle.bufs.entry(ctx.pid).or_insert_with(|| Vec::new()); + let sink_path = PathBuf::from( + String::from_utf8(buf.to_owned()).map_err(|_| Error::new(EINVAL))?, + ); + + self.output_tx.send(OutputCmd::AddSink(sink_path)).unwrap(); + + return Ok(buf.len()); + } + }; + + let handle_buf = bufs.entry(ctx.pid).or_insert_with(|| Vec::new()); let mut i = 0; while i < buf.len() { let b = buf[i]; - if handle_buf.is_empty() && !handle.context.is_empty() { - handle_buf.extend_from_slice(handle.context.as_bytes()); + if handle_buf.is_empty() && !context.is_empty() { + handle_buf.extend_from_slice(context.as_bytes()); handle_buf.extend_from_slice(b": "); } handle_buf.push(b); if b == b'\n' { - self.output_tx.send(mem::take(handle_buf)).unwrap(); + self.output_tx + .send(OutputCmd::Log(mem::take(handle_buf))) + .unwrap(); } i += 1; @@ -117,7 +157,7 @@ impl SchemeSync for LogScheme { fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result { let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - let scheme_path = b"log:"; + let scheme_path = b"/scheme/log/"; let mut i = 0; while i < buf.len() && i < scheme_path.len() { @@ -125,10 +165,13 @@ impl SchemeSync for LogScheme { i += 1; } + let path_bytes = match handle { + LogHandle::Log { context, .. } => context.as_bytes(), + LogHandle::AddSink => b"add_sink", + }; let mut j = 0; - let context_bytes = handle.context.as_bytes(); - while i < buf.len() && j < context_bytes.len() { - buf[i] = context_bytes[j]; + while i < buf.len() && j < path_bytes.len() { + buf[i] = path_bytes[j]; i += 1; j += 1; } From fb99ff5fa5920f3e10288ae77040adead0dabb80 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 6 Apr 2025 20:15:37 +0200 Subject: [PATCH 3/3] log: Add fixme about backfilling --- logd/src/scheme.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs index e10e77c1ad..d0bd430b4c 100644 --- a/logd/src/scheme.rs +++ b/logd/src/scheme.rs @@ -43,6 +43,7 @@ impl LogScheme { } } OutputCmd::AddSink(sink_path) => { + // FIXME backfill log messages that were sent to other log sinks match OpenOptions::new().write(true).open(&sink_path) { Ok(file) => files.push(file), Err(err) => {