diff --git a/backport-docs-note-that-we-only-support-no-more-than-500-unit.patch b/backport-docs-note-that-we-only-support-no-more-than-500-unit.patch new file mode 100644 index 0000000..60dc27f --- /dev/null +++ b/backport-docs-note-that-we-only-support-no-more-than-500-unit.patch @@ -0,0 +1,22 @@ +From 3db42578519edc87886b06428db5c31630957684 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 14 Jun 2023 11:35:13 +0800 +Subject: [PATCH] docs: note that we only support no more than 500 units by + default + +--- + docs/man/all.md | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/docs/man/all.md b/docs/man/all.md +index 2b3ec2c..337e156 100644 +--- a/docs/man/all.md ++++ b/docs/man/all.md +@@ -1,3 +1,4 @@ + # Warnings + + 1. 由于Rust使用String字符串,对于长度无限制, 建议用户在撰写配置文件时控制在合理的长度内. ++2. sysmaster默认支持的unit最大数量为500个,超过该值可能会一场退出。用户可以通过修改/etc/sysmaster/system.toml的DbSize配置提高unit上限。修改方法请参考:[外置db配置](./sysmaster.conf.md) +-- +2.30.2 + diff --git a/backport-feature-add-as_any-to-SubUnit-so-we-can-downcast-Sub.patch b/backport-feature-add-as_any-to-SubUnit-so-we-can-downcast-Sub.patch new file mode 100644 index 0000000..df47c1f --- /dev/null +++ b/backport-feature-add-as_any-to-SubUnit-so-we-can-downcast-Sub.patch @@ -0,0 +1,106 @@ +From 5fbd070f79a0526f647fb5bb734ad9edac9e2fe1 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:08:24 +0800 +Subject: [PATCH 3/9] feature: add as_any() to SubUnit so we can downcast + SubUnit trait to concrete componnent + +--- + coms/mount/src/unit.rs | 4 ++++ + coms/service/src/unit.rs | 4 ++++ + coms/socket/src/unit.rs | 5 +++++ + coms/target/src/unit.rs | 4 ++++ + core/lib/unit/base.rs | 3 +++ + 5 files changed, 20 insertions(+) + +diff --git a/coms/mount/src/unit.rs b/coms/mount/src/unit.rs +index dfa6087..dc84403 100644 +--- a/coms/mount/src/unit.rs ++++ b/coms/mount/src/unit.rs +@@ -64,6 +64,10 @@ impl MountUnit { + } + + impl SubUnit for MountUnit { ++ fn as_any(&self) -> &dyn std::any::Any { ++ self ++ } ++ + fn load(&self, _paths: Vec) -> Result<()> { + if let Some(u) = self.comm.owner() { + u.set_ignore_on_isolate(true) +diff --git a/coms/service/src/unit.rs b/coms/service/src/unit.rs +index c91a296..7ea3c44 100644 +--- a/coms/service/src/unit.rs ++++ b/coms/service/src/unit.rs +@@ -71,6 +71,10 @@ impl ReStation for ServiceUnit { + } + + impl SubUnit for ServiceUnit { ++ fn as_any(&self) -> &dyn std::any::Any { ++ self ++ } ++ + fn init(&self) { + todo!() + } +diff --git a/coms/socket/src/unit.rs b/coms/socket/src/unit.rs +index 198fafc..8e33ee8 100644 +--- a/coms/socket/src/unit.rs ++++ b/coms/socket/src/unit.rs +@@ -23,6 +23,7 @@ use crate::{ + use basic::logger; + use nix::sys::wait::WaitStatus; + use std::{path::PathBuf, rc::Rc}; ++use std::any::Any; + use sysmaster::error::*; + use sysmaster::exec::ExecContext; + use sysmaster::rel::{ReStation, Reliability}; +@@ -68,6 +69,10 @@ impl ReStation for SocketUnit { + } + + impl SubUnit for SocketUnit { ++ fn as_any(&self) -> &dyn Any { ++ self ++ } ++ + fn load(&self, paths: Vec) -> Result<()> { + log::debug!("socket begin to load conf file"); + self.config.load(paths, true)?; +diff --git a/coms/target/src/unit.rs b/coms/target/src/unit.rs +index 26b9950..e4caf5d 100644 +--- a/coms/target/src/unit.rs ++++ b/coms/target/src/unit.rs +@@ -120,6 +120,10 @@ impl Target { + } + + impl SubUnit for Target { ++ fn as_any(&self) -> &dyn std::any::Any { ++ self ++ } ++ + fn load(&self, _conf_str: Vec) -> Result<()> { + //todo add default dependency funnction need add + log::debug!("load for target"); +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index 0996f5d..d279295 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -17,6 +17,7 @@ use super::umif::UnitMngUtil; + use crate::error::*; + use nix::sys::wait::WaitStatus; + use nix::{sys::socket::UnixCredentials, unistd::Pid}; ++use std::any::Any; + use std::{collections::HashMap, path::PathBuf, rc::Rc}; + + ///The trait Defining Shared Behavior from Base Unit to SUB unit +@@ -72,6 +73,8 @@ pub trait UnitBase { + /// difference sub unit ref by dynamic trait + /// + pub trait SubUnit: ReStation + UnitMngUtil { ++ /// ++ fn as_any(&self) -> &dyn Any; + /// + fn init(&self) {} + +-- +2.30.2 + diff --git a/backport-feature-get-credential-from-the-connection-and-use-i.patch b/backport-feature-get-credential-from-the-connection-and-use-i.patch new file mode 100644 index 0000000..9200a76 --- /dev/null +++ b/backport-feature-get-credential-from-the-connection-and-use-i.patch @@ -0,0 +1,447 @@ +From ca86515f0d1cfcaae7d5552ef9f7df89cf6398d9 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 1 Jun 2023 15:38:02 +0800 +Subject: [PATCH] feature: get credential from the connection, and use it to + check if the request is send from root + +--- + core/bin/manager/commands.rs | 33 ++++++----- + core/bin/unit/entry/config.rs | 6 +- + core/bin/unit/util/unit_file.rs | 35 ++++++++++-- + libs/cmdproto/src/error.rs | 3 + + libs/cmdproto/src/proto/execute.rs | 68 ++++++++++++++++++++-- + libs/cmdproto/src/proto/frame.rs | 91 +++++++++++++++++++++++++----- + 6 files changed, 194 insertions(+), 42 deletions(-) + +diff --git a/core/bin/manager/commands.rs b/core/bin/manager/commands.rs +index 1279206..a8320e2 100644 +--- a/core/bin/manager/commands.rs ++++ b/core/bin/manager/commands.rs +@@ -73,21 +73,28 @@ where + } + + fn dispatch(&self, _e: &Events) -> i32 { +- log::trace!("Dispatching Command!"); +- + self.reli.set_last_frame1(ReliLastFrame::CmdOp as u32); +- match self.fd.incoming().next() { +- None => log::info!("None CommandRequest!"), +- Some(stream) => { +- log::trace!("{stream:?}"); +- if let Ok(s) = stream { +- let dispatch = ProstServerStream::new(s, self.command_action.clone()); +- match dispatch.process() { +- Ok(_) => (), +- Err(e) => log::error!("Commands failed: {:?}", e), +- } +- } ++ let client = match socket::accept(self.socket_fd) { ++ Err(e) => { ++ log::error!("Failed to accept connection: {}, ignoring.", e); ++ return 0; ++ } ++ Ok(v) => v, ++ }; ++ let cred = match socket::getsockopt(client, socket::sockopt::PeerCredentials) { ++ Err(e) => { ++ log::error!( ++ "Failed to get the credentials of the connection: {}, refuse any request.", ++ e ++ ); ++ None + } ++ Ok(v) => Some(v), ++ }; ++ let dispatch = ProstServerStream::new(client, self.command_action.clone(), cred); ++ match dispatch.process() { ++ Ok(_) => (), ++ Err(e) => log::error!("Commands failed: {:?}", e), + } + self.reli.clear_last_frame(); + +diff --git a/core/bin/unit/entry/config.rs b/core/bin/unit/entry/config.rs +index e629c77..705512d 100644 +--- a/core/bin/unit/entry/config.rs ++++ b/core/bin/unit/entry/config.rs +@@ -136,14 +136,12 @@ impl UeConfig { + + let unit_conf_frag = files.get_unit_id_fragment_pathbuf(name); + if unit_conf_frag.is_empty() { +- log::error!("config file for {} is not exist", name); +- return Err(format!("config file for {name} is not exist").into()); ++ return Err(format!("{name} doesn't have corresponding config file").into()); + } + // fragment + for v in unit_conf_frag { + if !v.exists() { +- log::error!("config file is not exist"); +- return Err(format!("config file is not exist {name}").into()); ++ return Err(format!("Config file {:?} of {name} doesn't exist", v).into()); + } + builder = builder.file(&v); + } +diff --git a/core/bin/unit/util/unit_file.rs b/core/bin/unit/util/unit_file.rs +index 31f5838..0871703 100644 +--- a/core/bin/unit/util/unit_file.rs ++++ b/core/bin/unit/util/unit_file.rs +@@ -133,12 +133,39 @@ impl UnitFileData { + format!("{v}/{name}") + }; + let tmp = Path::new(&path); +- if tmp.exists() && !tmp.is_symlink() { +- let path = format!("{}.toml", tmp.to_string_lossy()); +- if let Err(e) = std::fs::copy(tmp, &path) { ++ if !tmp.exists() { ++ continue; ++ } ++ /* Add .toml to the original path name */ ++ if !tmp.is_symlink() { ++ let path_toml = format!("{}.toml", tmp.to_string_lossy()); ++ let to = Path::new(&path_toml); ++ if let Err(e) = std::fs::copy(tmp, to) { + log::warn!("copy file content to toml file error: {}", e); + } +- let to = Path::new(&path); ++ pathbuf_fragment.push(to.to_path_buf()); ++ } else { ++ let real_path = match std::fs::read_link(tmp) { ++ Err(e) => { ++ log::error!("Failed to chase the symlink {:?}: {e}", tmp); ++ continue; ++ } ++ Ok(v) => v, ++ }; ++ /* Only support one-level symlink. */ ++ if real_path.is_symlink() { ++ continue; ++ } ++ let real_path = tmp.parent().unwrap().join(real_path); ++ let real_path = fs::canonicalize(&real_path).unwrap(); ++ let path_toml = format!("{}.toml", real_path.to_string_lossy()); ++ let to = Path::new(&path_toml); ++ if let Err(e) = std::fs::copy(&real_path, to) { ++ log::warn!( ++ "copy file content {:?} to toml file {path_toml} error: {e}", ++ real_path ++ ); ++ } + pathbuf_fragment.push(to.to_path_buf()); + } + } +diff --git a/libs/cmdproto/src/error.rs b/libs/cmdproto/src/error.rs +index 5d64109..618e6ad 100644 +--- a/libs/cmdproto/src/error.rs ++++ b/libs/cmdproto/src/error.rs +@@ -33,6 +33,9 @@ pub enum Error { + #[snafu(display("ReadStreamFailed"))] + ReadStream { msg: String }, + ++ #[snafu(display("SendStreamFailed"))] ++ SendStream { msg: String }, ++ + #[snafu(display("ManagerStartFailed"))] + ManagerStart { msg: String }, + } +diff --git a/libs/cmdproto/src/proto/execute.rs b/libs/cmdproto/src/proto/execute.rs +index f9ca73a..280b878 100644 +--- a/libs/cmdproto/src/proto/execute.rs ++++ b/libs/cmdproto/src/proto/execute.rs +@@ -18,7 +18,7 @@ use super::{ + + use crate::error::*; + use http::StatusCode; +-use nix; ++use nix::{self, sys::socket::UnixCredentials}; + use std::{fmt::Display, rc::Rc}; + + pub(crate) trait Executer { +@@ -27,6 +27,7 @@ pub(crate) trait Executer { + self, + manager: Rc, + call_back: Option String>, ++ cred: Option, + ) -> CommandResponse; + } + +@@ -73,7 +74,11 @@ pub trait ExecuterAction { + } + + /// Depending on the type of request +-pub(crate) fn dispatch(cmd: CommandRequest, manager: Rc) -> CommandResponse ++pub(crate) fn dispatch( ++ cmd: CommandRequest, ++ manager: Rc, ++ cred: Option, ++) -> CommandResponse + where + T: ExecuterAction, + { +@@ -89,10 +94,10 @@ where + }; + + match cmd.request_data { +- Some(RequestData::Ucomm(param)) => param.execute(manager, Some(call_back)), +- Some(RequestData::Mcomm(param)) => param.execute(manager, None), +- Some(RequestData::Syscomm(param)) => param.execute(manager, Some(call_back)), +- Some(RequestData::Ufile(param)) => param.execute(manager, Some(call_back)), ++ Some(RequestData::Ucomm(param)) => param.execute(manager, Some(call_back), cred), ++ Some(RequestData::Mcomm(param)) => param.execute(manager, None, cred), ++ Some(RequestData::Syscomm(param)) => param.execute(manager, Some(call_back), cred), ++ Some(RequestData::Ufile(param)) => param.execute(manager, Some(call_back), cred), + _ => CommandResponse::default(), + } + } +@@ -103,12 +108,45 @@ fn new_line_break(s: &mut String) { + } + } + ++fn response_if_credential_dissatisfied( ++ cred: Option, ++ command_is_allowed_for_nonroot: bool, ++) -> Option { ++ let sender = match cred { ++ None => { ++ return Some(CommandResponse { ++ status: StatusCode::OK.as_u16() as _, ++ error_code: 1, ++ message: "Failed to execute your command: cannot determine user credentials." ++ .to_string(), ++ }) ++ } ++ Some(v) => v.uid(), ++ }; ++ if sender != 0 && !command_is_allowed_for_nonroot { ++ return Some(CommandResponse { ++ status: StatusCode::OK.as_u16() as _, ++ error_code: 1, ++ message: "Failed to execute your command: Operation not permitted.".to_string(), ++ }); ++ } ++ None ++} ++ + impl Executer for UnitComm { + fn execute( + self, + manager: Rc, + call_back: Option String>, ++ cred: Option, + ) -> CommandResponse { ++ if let Some(v) = response_if_credential_dissatisfied( ++ cred, ++ [unit_comm::Action::Status].contains(&self.action()), ++ ) { ++ return v; ++ } ++ + let mut reply = String::new(); + let mut units: Vec = Vec::new(); + let mut error_code: u32 = 0; +@@ -197,7 +235,15 @@ impl Executer for MngrComm { + self, + manager: Rc, + _call_back: Option String>, ++ cred: Option, + ) -> CommandResponse { ++ if let Some(v) = response_if_credential_dissatisfied( ++ cred, ++ [mngr_comm::Action::Listunits].contains(&self.action()), ++ ) { ++ return v; ++ } ++ + match self.action() { + mngr_comm::Action::Reexec => { + manager.daemon_reexec(); +@@ -241,7 +287,12 @@ impl Executer for SysComm { + self, + manager: Rc, + _call_back: Option String>, ++ cred: Option, + ) -> CommandResponse { ++ if let Some(v) = response_if_credential_dissatisfied(cred, false) { ++ return v; ++ } ++ + let ret = if self.force { + let unit_name = self.action().to_string() + ".target"; + match manager.start(&unit_name) { +@@ -279,7 +330,12 @@ impl Executer for UnitFile { + self, + manager: Rc, + call_back: Option String>, ++ cred: Option, + ) -> CommandResponse { ++ if let Some(v) = response_if_credential_dissatisfied(cred, false) { ++ return v; ++ } ++ + let mut reply = String::new(); + let mut units: Vec = Vec::new(); + let mut error_code: u32 = 0; +diff --git a/libs/cmdproto/src/proto/frame.rs b/libs/cmdproto/src/proto/frame.rs +index 9b942a8..6b6912b 100644 +--- a/libs/cmdproto/src/proto/frame.rs ++++ b/libs/cmdproto/src/proto/frame.rs +@@ -12,6 +12,7 @@ + + //! Encapsulate the command request into a frame + use crate::error::*; ++use nix::sys::socket::{self, UnixCredentials}; + use prost::bytes::{BufMut, BytesMut}; + use prost::Message; + use std::{ +@@ -48,8 +49,49 @@ where + impl FrameCoder for CommandRequest {} + impl FrameCoder for CommandResponse {} + ++/// Read frame from accept fd. ++pub fn read_frame_from_fd(fd: i32, buf: &mut BytesMut) -> Result<()> { ++ // 1. Got the message length ++ let mut msg_len = [0_u8; USIZE_TO_U8_LENGTH]; ++ match socket::recv(fd, &mut msg_len, socket::MsgFlags::empty()) { ++ Ok(len) => { ++ if len != USIZE_TO_U8_LENGTH { ++ return Err(Error::ReadStream { ++ msg: "Invalid message length".to_string(), ++ }); ++ } ++ } ++ Err(e) => { ++ return Err(Error::ReadStream { msg: e.to_string() }); ++ } ++ } ++ let msg_len = get_msg_len(msg_len); ++ ++ // 2. Got the message ++ let mut tmp = vec![0; MAX_FRAME]; ++ let mut cur_len: usize = 0; ++ loop { ++ match socket::recv(fd, &mut tmp, socket::MsgFlags::empty()) { ++ Ok(len) => { ++ cur_len += len; ++ buf.put_slice(&tmp[..len]); ++ /* If there is no more message (len < MAX_FRAME), or ++ * we have got enough message (cur_len >= msg_len), ++ * then we finish reading. */ ++ if len < MAX_FRAME || cur_len >= msg_len { ++ break; ++ } ++ } ++ Err(e) => { ++ return Err(Error::ReadStream { msg: e.to_string() }); ++ } ++ } ++ } ++ Ok(()) ++} ++ + /// read frame from stream +-pub fn read_frame(stream: &mut S, buf: &mut BytesMut) -> Result<()> ++pub fn read_frame_from_stream(stream: &mut S, buf: &mut BytesMut) -> Result<()> + where + S: Read + Unpin + Send, + { +@@ -66,6 +108,9 @@ where + Ok(len) => { + cur_len += len; + buf.put_slice(&tmp[..len]); ++ /* If there is no more message (len < MAX_FRAME), or ++ * we have got enough message (cur_len >= msg_len), ++ * then we finish reading. */ + if len < MAX_FRAME || cur_len >= msg_len { + break; + } +@@ -89,9 +134,10 @@ fn get_msg_len(message: [u8; USIZE_TO_U8_LENGTH]) -> usize { + } + + /// Handle read and write of server-side socket +-pub struct ProstServerStream { +- inner: S, ++pub struct ProstServerStream { ++ accept_fd: i32, + manager: Rc, ++ cred: Option, + } + + /// Handle read and write of client-side socket +@@ -99,23 +145,23 @@ pub struct ProstClientStream { + inner: S, + } + +-impl ProstServerStream ++impl ProstServerStream + where +- S: Read + Write + Unpin + Send, + T: ExecuterAction, + { + /// new ProstServerStream +- pub fn new(stream: S, manager: Rc) -> Self { ++ pub fn new(accept_fd: i32, manager: Rc, cred: Option) -> Self { + Self { +- inner: stream, ++ accept_fd, + manager, ++ cred, + } + } + + /// process frame in server-side + pub fn process(mut self) -> Result<()> { + if let Ok(cmd) = self.recv() { +- let res = execute::dispatch(cmd, Rc::clone(&self.manager)); ++ let res = execute::dispatch(cmd, Rc::clone(&self.manager), self.cred); + self.send(res)?; + }; + Ok(()) +@@ -126,16 +172,32 @@ where + msg.encode_frame(&mut buf)?; + let encoded = buf.freeze(); + let msg_len = msg_len_vec(encoded.len()); +- self.inner.write_all(&msg_len).context(IoSnafu)?; +- self.inner.write_all(&encoded).context(IoSnafu)?; +- self.inner.flush().context(IoSnafu)?; ++ match socket::send(self.accept_fd, &msg_len, socket::MsgFlags::empty()) { ++ Ok(len) => { ++ if len != msg_len.len() { ++ return Err(Error::SendStream { ++ msg: "Invalid message length".to_string(), ++ }); ++ } ++ } ++ Err(e) => return Err(Error::SendStream { msg: e.to_string() }), ++ } ++ match socket::send(self.accept_fd, &encoded, socket::MsgFlags::empty()) { ++ Ok(len) => { ++ if len != encoded.len() { ++ return Err(Error::SendStream { ++ msg: "Invalid message length".to_string(), ++ }); ++ } ++ } ++ Err(e) => return Err(Error::SendStream { msg: e.to_string() }), ++ } + Ok(()) + } + + fn recv(&mut self) -> Result { + let mut buf = BytesMut::new(); +- let stream = &mut self.inner; +- read_frame(stream, &mut buf)?; ++ read_frame_from_fd(self.accept_fd, &mut buf)?; + CommandRequest::decode_frame(&mut buf) + } + } +@@ -169,8 +231,7 @@ where + + fn recv(&mut self) -> Result { + let mut buf = BytesMut::new(); +- let stream = &mut self.inner; +- read_frame(stream, &mut buf)?; ++ read_frame_from_stream(&mut self.inner, &mut buf)?; + CommandResponse::decode_frame(&mut buf) + } + } +-- +2.30.2 + diff --git a/backport-fix-add-has_source-to-events-and-use-this-in-socket..patch b/backport-fix-add-has_source-to-events-and-use-this-in-socket..patch new file mode 100644 index 0000000..3a49fac --- /dev/null +++ b/backport-fix-add-has_source-to-events-and-use-this-in-socket..patch @@ -0,0 +1,91 @@ +From 5798474ac1e7e5e41eb525884ecfff7a29f3800a Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:13:56 +0800 +Subject: [PATCH 5/9] fix: add has_source to events, and use this in + socket.watch_fds() to avoid adding same source to events loop. This PR also + contains some nonfunctional cleanups + +--- + coms/socket/src/mng.rs | 5 +++-- + libs/event/src/events.rs | 16 +++++++++++++++- + libs/event/src/poll/epoll.rs | 7 +++++-- + 3 files changed, 23 insertions(+), 5 deletions(-) + +diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs +index fe77517..aace9c7 100644 +--- a/coms/socket/src/mng.rs ++++ b/coms/socket/src/mng.rs +@@ -576,8 +576,9 @@ impl SocketMng { + continue; + } + let source = Rc::clone(mport); +- events.add_source(source).unwrap(); +- let source = Rc::clone(mport); ++ if !events.has_source(source.clone()) { ++ events.add_source(source.clone()).unwrap(); ++ } + events.set_enabled(source, EventState::On).unwrap(); + } + } +diff --git a/libs/event/src/events.rs b/libs/event/src/events.rs +index fba671f..ed7fa1c 100644 +--- a/libs/event/src/events.rs ++++ b/libs/event/src/events.rs +@@ -53,6 +53,11 @@ impl Events { + self.data.borrow_mut().add_source(source) + } + ++ /// for all: check if the source exists ++ pub fn has_source(&self, source: Rc) -> bool { ++ self.data.borrow().has_source(source) ++ } ++ + /// for all: delete source + pub fn del_source(&self, source: Rc) -> Result { + self.data.borrow_mut().del_source(source) +@@ -233,6 +238,11 @@ impl EventsData { + Ok(0) + } + ++ pub(self) fn has_source(&self, source: Rc) -> bool { ++ let token = source.token(); ++ self.sources.contains_key(&token) ++ } ++ + pub(self) fn del_source(&mut self, source: Rc) -> Result { + self.source_offline(&source)?; + +@@ -287,7 +297,11 @@ impl EventsData { + + pub(self) fn set_enabled(&mut self, source: Rc, state: EventState) -> Result { + let token = source.token(); +- ++ if let Some(current_state) = self.state.get(&token) { ++ if current_state == &state { ++ return Ok(0); ++ } ++ } + match state { + EventState::On | EventState::OneShot => { + self.source_online(&source)?; +diff --git a/libs/event/src/poll/epoll.rs b/libs/event/src/poll/epoll.rs +index 61926df..ad236ed 100644 +--- a/libs/event/src/poll/epoll.rs ++++ b/libs/event/src/poll/epoll.rs +@@ -77,8 +77,11 @@ impl Epoll { + } + + pub(crate) fn register(&mut self, fd: RawFd, event: &mut epoll_event) -> Result<()> { +- self.n_sources.fetch_add(1, Ordering::Relaxed); +- syscall!(epoll_ctl(self.epoll_fd, EPOLL_CTL_ADD, fd, event)).map(|_| ()) ++ let res = syscall!(epoll_ctl(self.epoll_fd, EPOLL_CTL_ADD, fd, event)).map(|_| ()); ++ if res.is_ok() { ++ self.n_sources.fetch_add(1, Ordering::Relaxed); ++ } ++ res + } + + pub(crate) fn reregister(&mut self, fd: RawFd, event: &mut epoll_event) -> Result<()> { +-- +2.30.2 + diff --git a/backport-fix-change-if-port.fd-is-valid-we-should-avoid-deali.patch b/backport-fix-change-if-port.fd-is-valid-we-should-avoid-deali.patch new file mode 100644 index 0000000..1cc78a2 --- /dev/null +++ b/backport-fix-change-if-port.fd-is-valid-we-should-avoid-deali.patch @@ -0,0 +1,29 @@ +From ef57fb8a85d78dfc6e7cbbf2ac6756da93ffd45f Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:15:32 +0800 +Subject: [PATCH 6/9] fix: change if port.fd() is valid, we should avoid + dealing with invalid port. + +--- + coms/socket/src/mng.rs | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs +index aace9c7..82fdcbe 100644 +--- a/coms/socket/src/mng.rs ++++ b/coms/socket/src/mng.rs +@@ -593,8 +593,9 @@ impl SocketMng { + + fn flush_ports(&self) { + for port in self.ports().iter() { +- port.flush_accept(); +- ++ if port.fd() < 0 { ++ continue; ++ } + port.flush_fd(); + } + } +-- +2.30.2 + diff --git a/backport-fix-change-the-socket-logic-to-keep-the-same-as-syst.patch b/backport-fix-change-the-socket-logic-to-keep-the-same-as-syst.patch new file mode 100644 index 0000000..c1ad3d0 --- /dev/null +++ b/backport-fix-change-the-socket-logic-to-keep-the-same-as-syst.patch @@ -0,0 +1,165 @@ +From 6ac9cdc2b5c38153a5faaf41ce8421b09aaf053e Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:20:33 +0800 +Subject: [PATCH 8/9] fix: change the socket logic to keep the same as systemd + 1. check the events number got from wait_for_events(), quick return when it + is 0. 2. make flush_accept() return the error. 3. close the accepted fd + instead port fd itself. + +--- + coms/socket/src/mng.rs | 1 + + coms/socket/src/port.rs | 54 ++++++++++++++++++++++++++--------------- + core/lib/error.rs | 28 +++++++++++++++++++++ + 3 files changed, 63 insertions(+), 20 deletions(-) + +diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs +index 0435827..da396de 100644 +--- a/coms/socket/src/mng.rs ++++ b/coms/socket/src/mng.rs +@@ -597,6 +597,7 @@ impl SocketMng { + if port.fd() < 0 { + continue; + } ++ let _ = port.flush_accept(); + port.flush_fd(); + } + } +diff --git a/coms/socket/src/port.rs b/coms/socket/src/port.rs +index 870cb70..0500669 100644 +--- a/coms/socket/src/port.rs ++++ b/coms/socket/src/port.rs +@@ -151,29 +151,43 @@ impl SocketPort { + } + } + +- pub(super) fn flush_accept(&self) { ++ pub(super) fn flush_accept(&self) -> Result<()> { + if let Ok(true) = socket::getsockopt(self.fd(), sockopt::AcceptConn) { + for _i in 1..1024 { +- while let Err(e) = io_util::wait_for_events(self.fd(), PollFlags::POLLIN, 0) { +- if let basic::Error::Nix { +- source: Errno::EINTR, +- } = e +- { +- continue; ++ let events = match io_util::wait_for_events(self.fd(), PollFlags::POLLIN, 0) { ++ Err(e) => { ++ if let basic::Error::Nix { ++ source: Errno::EINTR, ++ } = e ++ { ++ continue; ++ } ++ return Err(e.into()); + } +- return; ++ Ok(v) => v, ++ }; ++ if events == 0 { ++ return Ok(()); + } +- match socket::accept4(self.fd(), SockFlag::SOCK_NONBLOCK | SockFlag::SOCK_CLOEXEC) +- .map(|_| fd_util::close(self.fd())) +- { +- Ok(_) => {} +- Err(_e) => { +- // todo!(): if e == Errno::EAGAIN { return; } +- return; ++ let cfd = match socket::accept4( ++ self.fd(), ++ SockFlag::SOCK_NONBLOCK | SockFlag::SOCK_CLOEXEC, ++ ) { ++ Err(e) => { ++ if e == Errno::EAGAIN { ++ return Ok(()); ++ } ++ if error_is_accept_again(&e) { ++ continue; ++ } ++ return Err(e.into()); + } +- } ++ Ok(v) => v, ++ }; ++ fd_util::close(cfd); + } + } ++ Ok(()) + } + + pub(super) fn flush_fd(&self) { +@@ -356,7 +370,7 @@ mod tests { + assert_ne!(port.fd(), SOCKET_INVALID_FD); + assert_eq!(port.family(), AddressFamily::Inet); + +- port.flush_accept(); ++ assert!(port.flush_accept().is_ok()); + port.flush_fd(); + port.close(false); + } +@@ -387,7 +401,7 @@ mod tests { + assert_ne!(port.fd(), SOCKET_INVALID_FD); + assert_eq!(port.family(), AddressFamily::Unix); + +- port.flush_accept(); ++ assert!(port.flush_accept().is_ok()); + port.flush_fd(); + port.close(false); + } +@@ -424,7 +438,7 @@ mod tests { + assert_ne!(port.fd(), SOCKET_INVALID_FD); + assert_eq!(port.family(), AddressFamily::Netlink); + +- port.flush_accept(); ++ assert!(port.flush_accept().is_ok()); + port.flush_fd(); + port.close(false); + } +@@ -519,7 +533,7 @@ mod tests { + } + + // Rosource reclaim +- port.flush_accept(); ++ assert!(port.flush_accept().is_ok()); + port.flush_fd(); + port.close(false); + } +diff --git a/core/lib/error.rs b/core/lib/error.rs +index 100eb3c..331f367 100644 +--- a/core/lib/error.rs ++++ b/core/lib/error.rs +@@ -289,3 +289,31 @@ impl From for Error { + + /// new Result + pub type Result = std::result::Result; ++ ++pub fn error_is_disconnect(e: &Errno) -> bool { ++ [ ++ Errno::ECONNABORTED, ++ Errno::ECONNREFUSED, ++ Errno::ECONNRESET, ++ Errno::EHOSTDOWN, ++ Errno::EHOSTUNREACH, ++ Errno::ENETDOWN, ++ Errno::ENETRESET, ++ Errno::ENONET, ++ Errno::ENOPROTOOPT, ++ Errno::ENOTCONN, ++ Errno::EPIPE, ++ Errno::EPROTO, ++ Errno::ESHUTDOWN, ++ Errno::ETIMEDOUT, ++ ] ++ .contains(e) ++} ++ ++pub fn error_is_transient(e: &Errno) -> bool { ++ [Errno::EAGAIN, Errno::EINTR].contains(e) ++} ++ ++pub fn error_is_accept_again(e: &Errno) -> bool { ++ error_is_disconnect(e) || error_is_transient(e) || e == &Errno::EOPNOTSUPP ++} +-- +2.30.2 + diff --git a/backport-fix-check-if-the-given-unit-name-is-valid-before-we-.patch b/backport-fix-check-if-the-given-unit-name-is-valid-before-we-.patch new file mode 100644 index 0000000..a79d844 --- /dev/null +++ b/backport-fix-check-if-the-given-unit-name-is-valid-before-we-.patch @@ -0,0 +1,193 @@ +From 8123dcec5160b0d29e541cec1c9a027a1dd42c48 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 14 Jun 2023 15:52:40 +0800 +Subject: [PATCH] fix: check if the given unit name is valid before we prepare + the unit + +--- + core/bin/unit/base/load.rs | 8 ----- + core/bin/unit/manager.rs | 8 ++++- + core/bin/unit/uload.rs | 6 +++- + core/lib/unit/base.rs | 70 ++++++++++++++++++++++++++++++++++++++ + core/lib/unit/mod.rs | 3 +- + 5 files changed, 84 insertions(+), 11 deletions(-) + +diff --git a/core/bin/unit/base/load.rs b/core/bin/unit/base/load.rs +index 2281d06..700237d 100644 +--- a/core/bin/unit/base/load.rs ++++ b/core/bin/unit/base/load.rs +@@ -10,14 +10,6 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + +-#[allow(dead_code)] +-enum UnitNameFlags { +- Plain = 1, +- Instance = 2, +- Template = 4, +- Any = 1 | 2 | 4, +-} +- + #[allow(dead_code)] + enum UnitFileState { + Enabled, +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 4b3f4fb..cb5d957 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -50,7 +50,10 @@ use sysmaster::error::*; + use sysmaster::exec::ExecParameters; + use sysmaster::exec::{ExecCommand, ExecContext}; + use sysmaster::rel::{ReStation, ReStationKind, ReliLastFrame, Reliability}; +-use sysmaster::unit::{UmIf, UnitActiveState, UnitDependencyMask, UnitStatus, UnitType}; ++use sysmaster::unit::{ ++ unit_name_is_valid, UmIf, UnitActiveState, UnitDependencyMask, UnitNameFlags, UnitStatus, ++ UnitType, ++}; + use unit_submanager::UnitSubManagers; + + //#[derive(Debug)] +@@ -525,6 +528,9 @@ impl UnitManager { + + /// + pub fn units_get(&self, name: &str) -> Option> { ++ if !unit_name_is_valid(name, UnitNameFlags::PLAIN | UnitNameFlags::INSTANCE) { ++ return None; ++ } + self.db.units_get(name).map(|uxr| uxr.unit()) + } + +diff --git a/core/bin/unit/uload.rs b/core/bin/unit/uload.rs +index d972fb4..d6fea43 100644 +--- a/core/bin/unit/uload.rs ++++ b/core/bin/unit/uload.rs +@@ -22,7 +22,7 @@ use crate::utils::table::{TableOp, TableSubscribe}; + use basic::path_lookup::LookupPaths; + use std::cell::RefCell; + use std::rc::{Rc, Weak}; +-use sysmaster::unit::UnitType; ++use sysmaster::unit::{unit_name_is_valid, UnitNameFlags, UnitType}; + + //#[derive(Debug)] + pub(super) struct UnitLoad { +@@ -100,6 +100,10 @@ impl UnitLoadData { + } + + pub(self) fn prepare_unit(&self, name: &str) -> Option> { ++ if !unit_name_is_valid(name, UnitNameFlags::PLAIN | UnitNameFlags::INSTANCE) { ++ return None; ++ } ++ + if let Some(u) = self.db.units_get(name) { + if u.load_state() != UnitLoadState::NotFound { + return Some(Rc::clone(&u)); +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index f066ed7..555bb69 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -14,10 +14,14 @@ use super::super::rel::ReStation; + use super::kill::{KillContext, KillOperation}; + use super::state::{UnitActiveState, UnitNotifyFlags}; + use super::umif::UnitMngUtil; ++use super::UnitType; + use crate::error::*; ++use bitflags::bitflags; + use nix::sys::wait::WaitStatus; + use nix::{sys::socket::UnixCredentials, unistd::Pid}; + use std::any::Any; ++use std::num::ParseIntError; ++use std::str::FromStr; + use std::{collections::HashMap, path::PathBuf, rc::Rc}; + + ///The trait Defining Shared Behavior from Base Unit to SUB unit +@@ -206,3 +210,69 @@ macro_rules! declure_unitobj_plugin_with_param { + } + }; + } ++ ++bitflags! { ++ /// used to when check the given unit name is valid ++ pub struct UnitNameFlags: u8 { ++ /// Allow foo.service ++ const PLAIN = 1 << 0; ++ /// Allow foo@.service ++ const TEMPLATE = 1 << 1; ++ /// Allow foo@123.service ++ const INSTANCE = 1 << 2; ++ /// Any of the above ++ const ANY = Self::PLAIN.bits() | Self::TEMPLATE.bits() | Self::INSTANCE.bits(); ++ } ++} ++ ++/// The maximum length of a valid unit name ++const UNIT_NAME_MAX: usize = 255; ++ ++/// check if the given unit name is valid ++pub fn unit_name_is_valid(name: &str, flag: UnitNameFlags) -> bool { ++ if name.is_empty() { ++ return false; ++ } ++ if name.len() > UNIT_NAME_MAX { ++ return false; ++ } ++ /* Take foo@123.service for example, "foo@123" is its first_name, ++ * "foo" is prefix, "service" is its last_name, suffix, or type. */ ++ let (first_name, last_name) = match name.split_once('.') { ++ None => return false, ++ Some(v) => (v.0, v.1), ++ }; ++ ++ let unit_type = match unit_type_from_string(last_name) { ++ Err(_) => return false, ++ Ok(v) => v, ++ }; ++ ++ if unit_type == UnitType::UnitTypeInvalid { ++ return false; ++ } ++ ++ match first_name.split_once('@') { ++ None => flag.contains(UnitNameFlags::PLAIN), ++ Some(v) => { ++ /* "@" is the first character */ ++ if v.0.is_empty() { ++ return false; ++ } ++ /* "@" is the last character */ ++ if v.1.is_empty() { ++ return flag.contains(UnitNameFlags::TEMPLATE); ++ } ++ /* there is more than one "@" */ ++ if v.1.contains('@') { ++ return false; ++ } ++ flag.contains(UnitNameFlags::INSTANCE) ++ } ++ } ++} ++ ++/// convert the type string of one unit to UnitType ++pub fn unit_type_from_string(type_string: &str) -> Result { ++ UnitType::from_str(type_string) ++} +diff --git a/core/lib/unit/mod.rs b/core/lib/unit/mod.rs +index 7211aec..1eb565c 100644 +--- a/core/lib/unit/mod.rs ++++ b/core/lib/unit/mod.rs +@@ -11,11 +11,12 @@ + // See the Mulan PSL v2 for more details. + + //! +-pub use base::{SubUnit, UnitBase}; ++pub use base::{unit_name_is_valid, SubUnit, UnitBase, UnitNameFlags}; + pub use deps::{UnitDependencyMask, UnitRelationAtom, UnitRelations, UnitType}; + pub use kill::{KillContext, KillMode, KillOperation}; + pub use state::{UnitActiveState, UnitNotifyFlags, UnitStatus}; + pub use umif::{UmIf, UnitManagerObj, UnitMngUtil}; ++ + mod base; + mod deps; + mod kill; +-- +2.30.2 + diff --git a/backport-fix-check-if-the-returned-state-is-None.patch b/backport-fix-check-if-the-returned-state-is-None.patch new file mode 100644 index 0000000..74a4f0c --- /dev/null +++ b/backport-fix-check-if-the-returned-state-is-None.patch @@ -0,0 +1,28 @@ +From e0a828649165701afa9efa039650ddcd4afa4c6e Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 24 May 2023 16:45:10 +0800 +Subject: [PATCH] fix: check if the returned state is None + +--- + libs/event/src/events.rs | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/libs/event/src/events.rs b/libs/event/src/events.rs +index 7b0346d..8b29835 100644 +--- a/libs/event/src/events.rs ++++ b/libs/event/src/events.rs +@@ -108,7 +108,10 @@ impl Events { + } + + let top = first.unwrap(); +- let state = self.data.borrow().source_state(&top).unwrap(); ++ let state = match self.data.borrow().source_state(&top) { ++ None => return Ok(0), ++ Some(v) => v, ++ }; + match state { + EventState::Off => { + println!("set_enabled Off: {top:?}"); +-- +2.30.2 + diff --git a/backport-fix-compatible-with-rusc-1.60-lint-check.patch b/backport-fix-compatible-with-rusc-1.60-lint-check.patch new file mode 100644 index 0000000..94db0df --- /dev/null +++ b/backport-fix-compatible-with-rusc-1.60-lint-check.patch @@ -0,0 +1,557 @@ +From a8ca02c09ebffa5eabbb935be96b3864d8091549 Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Thu, 18 May 2023 16:45:47 +0800 +Subject: [PATCH] fix: compatible with rusc 1.60 lint check + +--- + core/bin/main.rs | 2 +- + core/bin/unit/execute/spawn.rs | 5 +- + core/bin/unit/uload.rs | 16 +- + core/lib/exec/cmd.rs | 1 - + exts/devmaster/src/lib/builtin/path_id.rs | 6 +- + exts/devmaster/src/lib/rules/rule_execute.rs | 156 ++++++------------- + exts/init/src/runtime/param.rs | 8 +- + exts/init/src/runtime/timer.rs | 1 + + exts/random_seed/src/random_seed.rs | 4 +- + libs/basic/src/user_group_util.rs | 2 +- + libs/event/src/timer.rs | 1 + + libs/macros/src/unit_conf_parse.rs | 13 +- + tests/docker_config_test.rs | 1 + + tests/docker_example.rs | 1 + + tests/docker_perf.rs | 1 + + tests/docker_reliable.rs | 1 + + 16 files changed, 81 insertions(+), 138 deletions(-) + +diff --git a/core/bin/main.rs b/core/bin/main.rs +index 26638d6..eb06ed6 100644 +--- a/core/bin/main.rs ++++ b/core/bin/main.rs +@@ -169,7 +169,7 @@ fn set_child_reaper() { + } + } + +-fn do_reexecute(args: &Vec, reload: bool) { ++fn do_reexecute(args: &[String], reload: bool) { + let args_size = args.len().max(MANAGER_ARGS_SIZE_MAX); + + let path; +diff --git a/core/bin/unit/execute/spawn.rs b/core/bin/unit/execute/spawn.rs +index cbde2b5..8e55970 100644 +--- a/core/bin/unit/execute/spawn.rs ++++ b/core/bin/unit/execute/spawn.rs +@@ -259,8 +259,7 @@ fn build_run_args( + let cmd = std::ffi::CString::new(cmdline.path().clone()).unwrap(); + let exec_name = std::ffi::CString::new(cmdline.path().clone()).unwrap(); + +- let mut args = Vec::new(); +- args.push(exec_name); ++ let mut args = vec![exec_name]; + + let var_regex = Regex::new(r"(\$[A-Z_]+)|(\$\{[A-Z_]+\})").unwrap(); + for arg in cmdline.argv() { +@@ -356,7 +355,7 @@ fn close_all_fds(fds: &[i32]) -> bool { + true + } + +-fn shift_fds(fds: &mut Vec) -> bool { ++fn shift_fds(fds: &mut [i32]) -> bool { + let mut start = 0; + loop { + let mut restart = -1; +diff --git a/core/bin/unit/uload.rs b/core/bin/unit/uload.rs +index a7d1bea..d972fb4 100644 +--- a/core/bin/unit/uload.rs ++++ b/core/bin/unit/uload.rs +@@ -210,14 +210,14 @@ impl UnitLoadData { + // dependency + for (relation, list) in config.deps.iter() { + for o_name in list { +- let tmp_unit: Rc; +- if let Some(o_unit) = self.push_dep_unit_into_load_queue(o_name) { +- //can not call unit_load directly, will be nested. +- tmp_unit = Rc::clone(&o_unit); +- } else { +- log::error!("create unit obj error in unit manager"); +- return; +- } ++ let tmp_unit: Rc = ++ if let Some(o_unit) = self.push_dep_unit_into_load_queue(o_name) { ++ //can not call unit_load directly, will be nested. ++ Rc::clone(&o_unit) ++ } else { ++ log::error!("create unit obj error in unit manager"); ++ return; ++ }; + + if let Err(_e) = self + .db +diff --git a/core/lib/exec/cmd.rs b/core/lib/exec/cmd.rs +index 406ee00..040b7f9 100644 +--- a/core/lib/exec/cmd.rs ++++ b/core/lib/exec/cmd.rs +@@ -116,7 +116,6 @@ impl DeserializeWith for ExecCommand { + continue; + } + +- #[allow(clippy::trim_split_whitespace)] + let mut command: Vec = Vec::new(); + let re = Regex::new(r"'([^']*)'|\S+").unwrap(); + for cap in re.captures_iter(cmd) { +diff --git a/exts/devmaster/src/lib/builtin/path_id.rs b/exts/devmaster/src/lib/builtin/path_id.rs +index 6d0de56..2ebaecd 100644 +--- a/exts/devmaster/src/lib/builtin/path_id.rs ++++ b/exts/devmaster/src/lib/builtin/path_id.rs +@@ -146,6 +146,7 @@ impl Builtin for PathId { + } + + impl PathId { ++ #[allow(clippy::ptr_arg)] + fn compose_path( + &self, + dev: Arc>, +@@ -982,6 +983,7 @@ impl PathId { + ) -> Option>> { + let mut dev = device.clone(); + let mut parent = device; ++ #[allow(clippy::while_let_loop)] + loop { + let subsystem = match parent.lock().unwrap().get_subsystem() { + Ok(str) => str, +diff --git a/exts/devmaster/src/lib/rules/rule_execute.rs b/exts/devmaster/src/lib/rules/rule_execute.rs +index 36acc8f..384d490 100644 +--- a/exts/devmaster/src/lib/rules/rule_execute.rs ++++ b/exts/devmaster/src/lib/rules/rule_execute.rs +@@ -111,7 +111,7 @@ impl ExecuteUnit { + } + + /// apply runtime substitution on all formatters in the string +- pub fn apply_format(&self, src: &String, replace_whitespace: bool) -> Result { ++ pub fn apply_format(&self, src: &str, replace_whitespace: bool) -> Result { + let mut idx: usize = 0; + let mut ret = String::new(); + while idx < src.len() { +@@ -370,7 +370,7 @@ impl ExecuteUnit { + } + + fn get_subst_type( +- s: &String, ++ s: &str, + idx: &mut usize, + strict: bool, + ) -> Result)>> { +@@ -1641,146 +1641,102 @@ mod tests { + let unit = ExecuteUnit::new(device); + // test long substitution formatter + // $kernel +- assert_eq!( +- unit.apply_format(&"$kernel".to_string(), false).unwrap(), +- "lo" +- ); ++ assert_eq!(unit.apply_format("$kernel", false).unwrap(), "lo"); + // $number +- assert_eq!( +- unit.apply_format(&"$number".to_string(), false).unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$number", false).unwrap(), ""); + // $devpath + assert_eq!( +- unit.apply_format(&"$devpath".to_string(), false).unwrap(), ++ unit.apply_format("$devpath", false).unwrap(), + "/devices/virtual/net/lo" + ); + // $id +- assert_eq!(unit.apply_format(&"$id".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("$id", false).unwrap(), ""); + // $driver +- assert_eq!( +- unit.apply_format(&"$driver".to_string(), false).unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$driver", false).unwrap(), ""); + // $attr{sysattr} + assert_eq!( +- unit.apply_format(&"$attr{address}".to_string(), false) +- .unwrap(), ++ unit.apply_format("$attr{address}", false).unwrap(), + "00:00:00:00:00:00" + ); + // $env{key} + assert_eq!( +- unit.apply_format(&"$env{DEVPATH}".to_string(), false) +- .unwrap(), ++ unit.apply_format("$env{DEVPATH}", false).unwrap(), + "/devices/virtual/net/lo" + ); + // $major +- assert_eq!( +- unit.apply_format(&"$major".to_string(), false).unwrap(), +- "0" +- ); ++ assert_eq!(unit.apply_format("$major", false).unwrap(), "0"); + // $minor +- assert_eq!( +- unit.apply_format(&"$minor".to_string(), false).unwrap(), +- "0" +- ); ++ assert_eq!(unit.apply_format("$minor", false).unwrap(), "0"); + // $result +- assert_eq!( +- unit.apply_format(&"$result".to_string(), false).unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$result", false).unwrap(), ""); + // $result{index} +- assert_eq!( +- unit.apply_format(&"$result{1}".to_string(), false).unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$result{1}", false).unwrap(), ""); + // $result{index+} +- assert_eq!( +- unit.apply_format(&"$result{1+}".to_string(), false) +- .unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$result{1+}", false).unwrap(), ""); + // $parent +- assert_eq!( +- unit.apply_format(&"$parent".to_string(), false).unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$parent", false).unwrap(), ""); + // $name +- assert_eq!( +- unit.apply_format(&"$name".to_string(), false).unwrap(), +- "lo" +- ); ++ assert_eq!(unit.apply_format("$name", false).unwrap(), "lo"); + // $links +- assert_eq!(unit.apply_format(&"$links".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("$links", false).unwrap(), ""); + // $root +- assert_eq!( +- unit.apply_format(&"$root".to_string(), false).unwrap(), +- "/dev" +- ); ++ assert_eq!(unit.apply_format("$root", false).unwrap(), "/dev"); + // $sys +- assert_eq!( +- unit.apply_format(&"$sys".to_string(), false).unwrap(), +- "/sys" +- ); ++ assert_eq!(unit.apply_format("$sys", false).unwrap(), "/sys"); + // $devnode +- assert_eq!( +- unit.apply_format(&"$devnode".to_string(), false).unwrap(), +- "" +- ); ++ assert_eq!(unit.apply_format("$devnode", false).unwrap(), ""); + + // test short substitution formatter + // %k +- assert_eq!(unit.apply_format(&"%k".to_string(), false).unwrap(), "lo"); ++ assert_eq!(unit.apply_format("%k", false).unwrap(), "lo"); + // %n +- assert_eq!(unit.apply_format(&"%n".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%n", false).unwrap(), ""); + // %p + assert_eq!( +- unit.apply_format(&"%p".to_string(), false).unwrap(), ++ unit.apply_format("%p", false).unwrap(), + "/devices/virtual/net/lo" + ); + // %b +- assert_eq!(unit.apply_format(&"%b".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%b", false).unwrap(), ""); + // %d +- assert_eq!(unit.apply_format(&"%d".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%d", false).unwrap(), ""); + // %s{sysattr} + assert_eq!( +- unit.apply_format(&"%s{address}".to_string(), false) +- .unwrap(), ++ unit.apply_format("%s{address}", false).unwrap(), + "00:00:00:00:00:00" + ); + // %E{key} + assert_eq!( +- unit.apply_format(&"%E{DEVPATH}".to_string(), false) +- .unwrap(), ++ unit.apply_format("%E{DEVPATH}", false).unwrap(), + "/devices/virtual/net/lo" + ); + // %M +- assert_eq!(unit.apply_format(&"%M".to_string(), false).unwrap(), "0"); ++ assert_eq!(unit.apply_format("%M", false).unwrap(), "0"); + // %m +- assert_eq!(unit.apply_format(&"%m".to_string(), false).unwrap(), "0"); ++ assert_eq!(unit.apply_format("%m", false).unwrap(), "0"); + // %c +- assert_eq!(unit.apply_format(&"%c".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%c", false).unwrap(), ""); + // %c{index} +- assert_eq!(unit.apply_format(&"%c{1}".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%c{1}", false).unwrap(), ""); + // %c{index+} +- assert_eq!(unit.apply_format(&"%c{1+}".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%c{1+}", false).unwrap(), ""); + // %P +- assert_eq!(unit.apply_format(&"%P".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%P", false).unwrap(), ""); + // %D +- assert_eq!(unit.apply_format(&"%D".to_string(), false).unwrap(), "lo"); ++ assert_eq!(unit.apply_format("%D", false).unwrap(), "lo"); + // %L +- assert_eq!(unit.apply_format(&"%L".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%L", false).unwrap(), ""); + // %r +- assert_eq!(unit.apply_format(&"%r".to_string(), false).unwrap(), "/dev"); ++ assert_eq!(unit.apply_format("%r", false).unwrap(), "/dev"); + // %S +- assert_eq!(unit.apply_format(&"%S".to_string(), false).unwrap(), "/sys"); ++ assert_eq!(unit.apply_format("%S", false).unwrap(), "/sys"); + // %N +- assert_eq!(unit.apply_format(&"%N".to_string(), false).unwrap(), ""); ++ assert_eq!(unit.apply_format("%N", false).unwrap(), ""); + + // $$ +- assert_eq!(unit.apply_format(&"$$".to_string(), false).unwrap(), "$"); ++ assert_eq!(unit.apply_format("$$", false).unwrap(), "$"); + // %% +- assert_eq!(unit.apply_format(&"%%".to_string(), false).unwrap(), "%"); ++ assert_eq!(unit.apply_format("%%", false).unwrap(), "%"); + } + + #[test] +@@ -1790,30 +1746,12 @@ mod tests { + Device::from_subsystem_sysname("block".to_string(), "sda1".to_string()).unwrap(), + )); + let unit = ExecuteUnit::new(device); +- assert_eq!( +- unit.apply_format(&"$number".to_string(), false).unwrap(), +- "1" +- ); +- assert_eq!( +- unit.apply_format(&"$major".to_string(), false).unwrap(), +- "8" +- ); +- assert_eq!( +- unit.apply_format(&"$minor".to_string(), false).unwrap(), +- "1" +- ); +- assert_eq!( +- unit.apply_format(&"$driver".to_string(), false).unwrap(), +- "" +- ); +- assert_eq!(unit.apply_format(&"$id".to_string(), false).unwrap(), ""); +- assert_eq!( +- unit.apply_format(&"$parent".to_string(), false).unwrap(), +- "sda" +- ); +- assert_eq!( +- unit.apply_format(&"$devnode".to_string(), false).unwrap(), +- "/dev/sda1" +- ); ++ assert_eq!(unit.apply_format("$number", false).unwrap(), "1"); ++ assert_eq!(unit.apply_format("$major", false).unwrap(), "8"); ++ assert_eq!(unit.apply_format("$minor", false).unwrap(), "1"); ++ assert_eq!(unit.apply_format("$driver", false).unwrap(), ""); ++ assert_eq!(unit.apply_format("$id", false).unwrap(), ""); ++ assert_eq!(unit.apply_format("$parent", false).unwrap(), "sda"); ++ assert_eq!(unit.apply_format("$devnode", false).unwrap(), "/dev/sda1"); + } + } +diff --git a/exts/init/src/runtime/param.rs b/exts/init/src/runtime/param.rs +index 7aed5dc..c795a8c 100644 +--- a/exts/init/src/runtime/param.rs ++++ b/exts/init/src/runtime/param.rs +@@ -13,7 +13,7 @@ const DEFAULT_TIMECNT: i64 = 5; + const DEFAULT_TIMEWAIT: i64 = 10; + const INIT_PARAM: i32 = 0; + // const SYSMASTER_PARAM: i32 = 1; +-type Callback = fn(arg: &str, key: &String, init_param: &mut InitParam); ++type Callback = fn(arg: &str, key: &str, init_param: &mut InitParam); + + struct Dispatch<'a> { + key: &'a str, +@@ -34,7 +34,7 @@ const PARAM_TABLE: &[Dispatch] = &[ + }, + ]; + +-fn parse_timecnt(arg: &str, key: &String, init_param: &mut InitParam) { ++fn parse_timecnt(arg: &str, key: &str, init_param: &mut InitParam) { + let str1 = &arg[key.len()..]; + if let Ok(value) = str1.parse::() { + if value >= 2 { +@@ -43,7 +43,7 @@ fn parse_timecnt(arg: &str, key: &String, init_param: &mut InitParam) { + } + } + +-fn parse_timewait(arg: &str, key: &String, init_param: &mut InitParam) { ++fn parse_timewait(arg: &str, key: &str, init_param: &mut InitParam) { + let str1 = &arg[key.len()..]; + if let Ok(value) = str1.parse::() { + if value >= DEFAULT_TIMEWAIT { +@@ -78,7 +78,7 @@ impl Param { + for table in PARAM_TABLE { + if arg.starts_with(table.key) && table.callback.is_some() { + if INIT_PARAM == table.param_type { +- table.callback.unwrap()(&arg, &table.key.to_string(), &mut self.init_param); ++ table.callback.unwrap()(&arg, table.key, &mut self.init_param); + } else { + self.manager_param.push(arg); + } +diff --git a/exts/init/src/runtime/timer.rs b/exts/init/src/runtime/timer.rs +index c054c6c..f7b5f30 100644 +--- a/exts/init/src/runtime/timer.rs ++++ b/exts/init/src/runtime/timer.rs +@@ -55,6 +55,7 @@ impl Timer { + } + } + ++ #[allow(clippy::wrong_self_convention)] + pub fn is_time_out(&mut self, event: EpollEvent) -> Result { + if self.epoll.is_err(event) { + return Err(Errno::EIO); +diff --git a/exts/random_seed/src/random_seed.rs b/exts/random_seed/src/random_seed.rs +index 2130b2e..f862163 100644 +--- a/exts/random_seed/src/random_seed.rs ++++ b/exts/random_seed/src/random_seed.rs +@@ -58,7 +58,7 @@ fn random_pool_size() -> usize { + } + } + +-pub fn get_random(data: &mut Vec, flags: u32) -> Result { ++pub fn get_random(data: &mut [u8], flags: u32) -> Result { + let size; + unsafe { + size = libc::getrandom(data.as_mut_ptr() as *mut libc::c_void, data.len(), flags); +@@ -103,7 +103,7 @@ ioctl_write_ptr!( + ENTROPY_SETOPTIONS, + rand_pool_info + ); +-fn random_write_entropy(random_fd: &mut File, data: &mut Vec, credit: bool) -> bool { ++fn random_write_entropy(random_fd: &mut File, data: &mut [u8], credit: bool) -> bool { + assert!(!data.is_empty()); + + if data.is_empty() { +diff --git a/libs/basic/src/user_group_util.rs b/libs/basic/src/user_group_util.rs +index bd9e4b2..7af8d62 100644 +--- a/libs/basic/src/user_group_util.rs ++++ b/libs/basic/src/user_group_util.rs +@@ -117,7 +117,7 @@ pub fn parse_gid(gid_str: &String) -> Result { + } + + /// Parse a string as Username +-pub fn parse_name(name_str: &String) -> Result { ++pub fn parse_name(name_str: &str) -> Result { + if name_str.is_empty() { + return Err(Error::Invalid { + what: "Username is empty".to_string(), +diff --git a/libs/event/src/timer.rs b/libs/event/src/timer.rs +index 31c808c..a94025b 100644 +--- a/libs/event/src/timer.rs ++++ b/libs/event/src/timer.rs +@@ -126,6 +126,7 @@ impl Timer { + } + } + ++ #[allow(clippy::wrong_self_convention)] + pub fn is_empty(&mut self, et: &EventType) -> bool { + if let Some(inner) = self.timer_set.get_mut(et) { + return inner.data.is_empty(); +diff --git a/libs/macros/src/unit_conf_parse.rs b/libs/macros/src/unit_conf_parse.rs +index de9c6f0..ab0c0a2 100644 +--- a/libs/macros/src/unit_conf_parse.rs ++++ b/libs/macros/src/unit_conf_parse.rs +@@ -128,13 +128,12 @@ fn gererate_setter_functions( + let mut final_stream = proc_macro2::TokenStream::new(); + + for (ident, _type) in idents.iter().zip(types.iter()) { +- let token_piece; + let set_field_name = format!("set_{}", ident.as_ref().unwrap()); + let get_field_name = format!("get_{}", ident.as_ref().unwrap()); + let set_field_ident = syn::Ident::new(&set_field_name, ident.span()); + let get_field_ident = syn::Ident::new(&get_field_name, ident.span()); +- if let Some(inner_ty) = get_option_inner_type(_type) { +- token_piece = quote! { ++ let token_piece = if let Some(inner_ty) = get_option_inner_type(_type) { ++ quote! { + #vis fn #set_field_ident(&mut self, #ident: #inner_ty) -> &mut Self{ + self.#ident = std::option::Option::Some(#ident); + self +@@ -146,9 +145,9 @@ fn gererate_setter_functions( + return std::option::Option::Some(self.#ident.as_ref().unwrap().clone()); + } + } +- }; ++ } + } else { +- token_piece = quote! { ++ quote! { + #vis fn #set_field_ident(&mut self, #ident: #_type) -> &mut Self{ + self.#ident = #ident; + self +@@ -156,8 +155,8 @@ fn gererate_setter_functions( + #vis fn #get_field_ident(&self) -> #_type{ + return self.#ident.clone(); + } +- }; +- } ++ } ++ }; + final_stream.extend(token_piece); + } + Ok(final_stream) +diff --git a/tests/docker_config_test.rs b/tests/docker_config_test.rs +index a3969ee..b98c612 100644 +--- a/tests/docker_config_test.rs ++++ b/tests/docker_config_test.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++#[rustfmt::skip] + mod common; + + #[test] +diff --git a/tests/docker_example.rs b/tests/docker_example.rs +index a2f2952..97b1127 100644 +--- a/tests/docker_example.rs ++++ b/tests/docker_example.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++#[rustfmt::skip] + mod common; + + #[test] +diff --git a/tests/docker_perf.rs b/tests/docker_perf.rs +index 2a45ab0..41021ed 100644 +--- a/tests/docker_perf.rs ++++ b/tests/docker_perf.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++#[rustfmt::skip] + mod common; + + #[test] +diff --git a/tests/docker_reliable.rs b/tests/docker_reliable.rs +index 63a2420..8db2c0d 100644 +--- a/tests/docker_reliable.rs ++++ b/tests/docker_reliable.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++#[rustfmt::skip] + mod common; + + #[test] +-- +2.30.2 + diff --git a/backport-fix-compatible-with-rustc-1.60.patch b/backport-fix-compatible-with-rustc-1.60.patch index cd66b59..fcdf394 100644 --- a/backport-fix-compatible-with-rustc-1.60.patch +++ b/backport-fix-compatible-with-rustc-1.60.patch @@ -416,5 +416,5 @@ index ac39820..d9c5289 100644 type Err = crate::error::Error; -- -2.33.0 +2.30.2 diff --git a/backport-fix-don-t-mount-all-subsystem-to-every-sys-fs-cgroup.patch b/backport-fix-don-t-mount-all-subsystem-to-every-sys-fs-cgroup.patch new file mode 100644 index 0000000..ed696ef --- /dev/null +++ b/backport-fix-don-t-mount-all-subsystem-to-every-sys-fs-cgroup.patch @@ -0,0 +1,26 @@ +From a2563cafd9b64d0703b69bc4dddc653d5c092bf3 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Tue, 13 Jun 2023 20:21:31 +0800 +Subject: [PATCH] fix: don't mount all subsystem to every /sys/fs/cgroup + directory + +--- + core/bin/mount/setup.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/core/bin/mount/setup.rs b/core/bin/mount/setup.rs +index ccc6a25..6a13626 100644 +--- a/core/bin/mount/setup.rs ++++ b/core/bin/mount/setup.rs +@@ -428,7 +428,7 @@ pub fn mount_cgroup_controllers() -> Result<()> { + } else { + (controllers[index].to_string(), "".to_string()) + }; +- ++ m_point.options = Some(target.to_string()); + let target_dir = Path::new(CG_BASE_DIR).join(target); + let target = target_dir.to_str().expect("invalid cgroup path"); + m_point.set_target(target); +-- +2.30.2 + diff --git a/backport-fix-enable-trigger-for-socket-and-use-this-interface.patch b/backport-fix-enable-trigger-for-socket-and-use-this-interface.patch new file mode 100644 index 0000000..5166c4e --- /dev/null +++ b/backport-fix-enable-trigger-for-socket-and-use-this-interface.patch @@ -0,0 +1,105 @@ +From 86f01db06f5c20416a17a88a207ffb012588d0d8 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:17:52 +0800 +Subject: [PATCH 7/9] fix: enable trigger() for socket, and use this interface + to check service state make socket reenter listening state when it triggered + service enters dead state. + +--- + coms/socket/src/mng.rs | 3 ++- + coms/socket/src/unit.rs | 16 ++++++++++++++++ + core/bin/unit/entry/uentry.rs | 5 +++++ + core/bin/unit/entry/unitx.rs | 4 +++- + core/lib/unit/base.rs | 3 +++ + 5 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs +index 82fdcbe..0435827 100644 +--- a/coms/socket/src/mng.rs ++++ b/coms/socket/src/mng.rs +@@ -341,8 +341,9 @@ impl SocketMng { + self.set_state(SocketState::StartPost); + } + +- fn enter_listening(&self) { ++ pub(crate) fn enter_listening(&self) { + log::debug!("enter start listening state"); ++ /* Seem logic as systemd's socket has configured FlushPending=yes */ + if !self.config.config_data().borrow().Socket.Accept { + self.flush_ports(); + } +diff --git a/coms/socket/src/unit.rs b/coms/socket/src/unit.rs +index 8e33ee8..d96c258 100644 +--- a/coms/socket/src/unit.rs ++++ b/coms/socket/src/unit.rs +@@ -115,6 +115,22 @@ impl SubUnit for SocketUnit { + Ok(()) + } + ++ fn trigger(&self, other: &String) { ++ let um = self.comm.um(); ++ let service_state = um.get_subunit_state(other); ++ if [ ++ "dead".to_string(), ++ "failed".to_string(), ++ "finalsigterm".to_string(), ++ "finalsigkill".to_string(), ++ "autorestart".to_string(), ++ ] ++ .contains(&service_state) ++ { ++ self.mng.enter_listening(); ++ } ++ } ++ + fn sigchld_events(&self, wait_status: WaitStatus) { + self.mng.sigchld_event(wait_status) + } +diff --git a/core/bin/unit/entry/uentry.rs b/core/bin/unit/entry/uentry.rs +index 307240b..f6b4db4 100644 +--- a/core/bin/unit/entry/uentry.rs ++++ b/core/bin/unit/entry/uentry.rs +@@ -545,6 +545,11 @@ impl Unit { + self.config.clone() + } + ++ pub(super) fn trigger(&self, other: &Self) { ++ let other_unit_id = other.id(); ++ self.sub.trigger(other_unit_id); ++ } ++ + pub(super) fn in_load_queue(&self) -> bool { + self.load.in_load_queue() + } +diff --git a/core/bin/unit/entry/unitx.rs b/core/bin/unit/entry/unitx.rs +index d9878f4..92b4ebb 100644 +--- a/core/bin/unit/entry/unitx.rs ++++ b/core/bin/unit/entry/unitx.rs +@@ -106,7 +106,9 @@ impl UnitX { + self.0.sigchld_events(wait_status) + } + +- pub(crate) fn trigger(&self, _other: &Self) {} ++ pub(crate) fn trigger(&self, other: &Self) { ++ self.0.trigger(other); ++ } + pub(crate) fn in_load_queue(&self) -> bool { + self.0.in_load_queue() + } +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index d279295..8d76cab 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -127,6 +127,9 @@ pub trait SubUnit: ReStation + UnitMngUtil { + Vec::new() + } + ++ /// ++ fn trigger(&self, _other: &String) {} ++ + ///Get the the unit state + /// + /// Every sub unit can define self states and map to [`UnitActiveState`] +-- +2.30.2 + diff --git a/backport-fix-fix-some-cargo-clippies.patch b/backport-fix-fix-some-cargo-clippies.patch new file mode 100644 index 0000000..c496419 --- /dev/null +++ b/backport-fix-fix-some-cargo-clippies.patch @@ -0,0 +1,122 @@ +From 4490bcd3d40b15f22446af46500039d2cbd37bf9 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:24:36 +0800 +Subject: [PATCH 9/9] fix: fix some cargo clippies + +--- + coms/socket/src/unit.rs | 4 ++-- + core/bin/unit/data/table.rs | 3 +-- + core/bin/unit/datastore/sets.rs | 2 +- + core/bin/utils/table.rs | 6 +----- + core/lib/error.rs | 3 +++ + core/lib/unit/base.rs | 2 +- + 6 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/coms/socket/src/unit.rs b/coms/socket/src/unit.rs +index d96c258..9f0f6ce 100644 +--- a/coms/socket/src/unit.rs ++++ b/coms/socket/src/unit.rs +@@ -22,8 +22,8 @@ use crate::{ + }; + use basic::logger; + use nix::sys::wait::WaitStatus; +-use std::{path::PathBuf, rc::Rc}; + use std::any::Any; ++use std::{path::PathBuf, rc::Rc}; + use sysmaster::error::*; + use sysmaster::exec::ExecContext; + use sysmaster::rel::{ReStation, Reliability}; +@@ -115,7 +115,7 @@ impl SubUnit for SocketUnit { + Ok(()) + } + +- fn trigger(&self, other: &String) { ++ fn trigger(&self, other: &str) { + let um = self.comm.um(); + let service_state = um.get_subunit_state(other); + if [ +diff --git a/core/bin/unit/data/table.rs b/core/bin/unit/data/table.rs +index 161ac5f..256e8df 100644 +--- a/core/bin/unit/data/table.rs ++++ b/core/bin/unit/data/table.rs +@@ -60,8 +60,7 @@ impl DataManager { + ud_config: UnitDepConf, + ) -> Option { + { +- let old = self.tables.0.insert(u_name, ud_config); +- old ++ self.tables.0.insert(u_name, ud_config) + } + } + +diff --git a/core/bin/unit/datastore/sets.rs b/core/bin/unit/datastore/sets.rs +index 538df8f..9a94a4b 100644 +--- a/core/bin/unit/datastore/sets.rs ++++ b/core/bin/unit/datastore/sets.rs +@@ -62,7 +62,7 @@ impl UnitSets { + .borrow() + .get_all() + .iter() +- .map(|ur| Rc::clone(ur)) ++ .map(Rc::clone) + .collect::>() + } + +diff --git a/core/bin/utils/table.rs b/core/bin/utils/table.rs +index e1768d2..482d168 100644 +--- a/core/bin/utils/table.rs ++++ b/core/bin/utils/table.rs +@@ -82,11 +82,7 @@ where + } + + pub fn get_all(&self) -> Vec { +- self.data +- .borrow() +- .values() +- .map(|v| v.clone()) +- .collect::>() ++ self.data.borrow().values().cloned().collect::>() + } + + pub fn subscribe( +diff --git a/core/lib/error.rs b/core/lib/error.rs +index 331f367..72471db 100644 +--- a/core/lib/error.rs ++++ b/core/lib/error.rs +@@ -290,6 +290,7 @@ impl From for Error { + /// new Result + pub type Result = std::result::Result; + ++/// check if the error is disconnect + pub fn error_is_disconnect(e: &Errno) -> bool { + [ + Errno::ECONNABORTED, +@@ -310,10 +311,12 @@ pub fn error_is_disconnect(e: &Errno) -> bool { + .contains(e) + } + ++/// check if the error is transient + pub fn error_is_transient(e: &Errno) -> bool { + [Errno::EAGAIN, Errno::EINTR].contains(e) + } + ++/// check if the error is accept or again + pub fn error_is_accept_again(e: &Errno) -> bool { + error_is_disconnect(e) || error_is_transient(e) || e == &Errno::EOPNOTSUPP + } +diff --git a/core/lib/unit/base.rs b/core/lib/unit/base.rs +index 8d76cab..2ec3e73 100644 +--- a/core/lib/unit/base.rs ++++ b/core/lib/unit/base.rs +@@ -128,7 +128,7 @@ pub trait SubUnit: ReStation + UnitMngUtil { + } + + /// +- fn trigger(&self, _other: &String) {} ++ fn trigger(&self, _other: &str) {} + + ///Get the the unit state + /// +-- +2.30.2 + diff --git a/backport-fix-fstab-use-fixed-inotify-version-0.10.0-to-be-com.patch b/backport-fix-fstab-use-fixed-inotify-version-0.10.0-to-be-com.patch new file mode 100644 index 0000000..92ceec9 --- /dev/null +++ b/backport-fix-fstab-use-fixed-inotify-version-0.10.0-to-be-com.patch @@ -0,0 +1,28 @@ +From 71b0283e4c34078497c4aced37234949d833f45c Mon Sep 17 00:00:00 2001 +From: chenjiayi +Date: Wed, 7 Jun 2023 00:40:37 +0800 +Subject: [PATCH] fix(fstab): use fixed inotify version 0.10.0 to be compatible + with rustc 1.60 + +Latest inotify crate 0.10.1 requires rustc 1.63.0. Previously we didn't +state the minimum version number of inotify, which lead to cargo +automatically use the latest version and fails to build. +--- + exts/fstab/Cargo.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/exts/fstab/Cargo.toml b/exts/fstab/Cargo.toml +index 3445698..59ba4c4 100644 +--- a/exts/fstab/Cargo.toml ++++ b/exts/fstab/Cargo.toml +@@ -6,6 +6,6 @@ edition = "2021" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + [dependencies] +-inotify = "0.10" ++inotify = "=0.10.0" + log = "0.4" + nix = "0.24" +-- +2.30.2 + diff --git a/backport-fix-move-RefCell-to-the-inside-of-Table-no-functiona.patch b/backport-fix-move-RefCell-to-the-inside-of-Table-no-functiona.patch new file mode 100644 index 0000000..d84c124 --- /dev/null +++ b/backport-fix-move-RefCell-to-the-inside-of-Table-no-functiona.patch @@ -0,0 +1,399 @@ +From b2800ac267a76c19ce3229b031d809c4539ba5e7 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 11:10:42 +0800 +Subject: [PATCH 4/9] fix: move RefCell to the inside of Table, no functional + change + +--- + core/bin/unit/data/dep_conf.rs | 2 +- + core/bin/unit/data/state.rs | 2 +- + core/bin/unit/data/table.rs | 49 +++++++++------------- + core/bin/unit/datastore/sets.rs | 2 +- + core/bin/unit/entry/ratelimit.rs | 2 +- + core/bin/utils/table.rs | 71 +++++++++++++++++--------------- + 6 files changed, 60 insertions(+), 68 deletions(-) + +diff --git a/core/bin/unit/data/dep_conf.rs b/core/bin/unit/data/dep_conf.rs +index 9c203c5..e61ce5b 100644 +--- a/core/bin/unit/data/dep_conf.rs ++++ b/core/bin/unit/data/dep_conf.rs +@@ -13,7 +13,7 @@ + use std::collections::HashMap; + use sysmaster::unit::UnitRelations; + +-#[derive(Default)] ++#[derive(Default, Clone)] + pub struct UnitDepConf { + pub deps: HashMap>, + } +diff --git a/core/bin/unit/data/state.rs b/core/bin/unit/data/state.rs +index fcdd51e..68e8607 100644 +--- a/core/bin/unit/data/state.rs ++++ b/core/bin/unit/data/state.rs +@@ -12,7 +12,7 @@ + + use sysmaster::unit::{UnitActiveState, UnitNotifyFlags}; + +-#[derive(Debug)] ++#[derive(Debug, Clone)] + pub(crate) struct UnitState { + pub(crate) os: UnitActiveState, + pub(crate) ns: UnitActiveState, +diff --git a/core/bin/unit/data/table.rs b/core/bin/unit/data/table.rs +index 480a026..161ac5f 100644 +--- a/core/bin/unit/data/table.rs ++++ b/core/bin/unit/data/table.rs +@@ -15,17 +15,16 @@ use super::state::UnitState; + use crate::job::JobResult; + use crate::unit::entry::StartLimitResult; + use crate::utils::table::{Table, TableSubscribe}; +-use std::cell::RefCell; + use std::rc::Rc; + use sysmaster::rel::ReStation; + + #[allow(clippy::type_complexity)] + pub struct DataManager { + tables: ( +- RefCell>, // [0]unit-dep-config +- RefCell>, // [1]unit-state +- RefCell>, // [2]unit-start-limit-hit +- RefCell>, // [3] unit-job-timeout ++ Table, // [0]unit-dep-config ++ Table, // [1]unit-state ++ Table, // [2]unit-start-limit-hit ++ Table, // [3] unit-job-timeout + ), + } + +@@ -35,8 +34,8 @@ impl ReStation for DataManager { + + // reload + fn entry_clear(&self) { +- self.tables.0.borrow_mut().data_clear(); +- self.tables.1.borrow_mut().data_clear(); ++ self.tables.0.data_clear(); ++ self.tables.1.data_clear(); + } + } + +@@ -51,12 +50,7 @@ impl Drop for DataManager { + impl DataManager { + pub fn new() -> DataManager { + DataManager { +- tables: ( +- RefCell::new(Table::new()), +- RefCell::new(Table::new()), +- RefCell::new(Table::new()), +- RefCell::new(Table::new()), +- ), ++ tables: (Table::new(), Table::new(), Table::new(), Table::new()), + } + } + +@@ -66,7 +60,7 @@ impl DataManager { + ud_config: UnitDepConf, + ) -> Option { + { +- let old = self.tables.0.borrow_mut().insert(u_name, ud_config); ++ let old = self.tables.0.insert(u_name, ud_config); + old + } + } +@@ -76,8 +70,7 @@ impl DataManager { + name: &str, + subscriber: Rc>, + ) -> Option>> { +- let mut table = self.tables.0.borrow_mut(); +- table.subscribe(name.to_string(), subscriber) ++ self.tables.0.subscribe(name.to_string(), subscriber) + } + + pub(crate) fn insert_unit_state( +@@ -85,8 +78,7 @@ impl DataManager { + u_name: String, + u_state: UnitState, + ) -> Option { +- let mut table = self.tables.1.borrow_mut(); +- table.insert(u_name, u_state) ++ self.tables.1.insert(u_name, u_state) + } + + pub(crate) fn register_unit_state( +@@ -94,8 +86,7 @@ impl DataManager { + name: &str, + subscriber: Rc>, + ) -> Option>> { +- let mut table = self.tables.1.borrow_mut(); +- table.subscribe(name.to_string(), subscriber) ++ self.tables.1.subscribe(name.to_string(), subscriber) + } + + pub(crate) fn insert_start_limit_result( +@@ -103,8 +94,7 @@ impl DataManager { + u_name: String, + start_limit_res: StartLimitResult, + ) -> Option { +- let mut table = self.tables.2.borrow_mut(); +- table.insert(u_name, start_limit_res) ++ self.tables.2.insert(u_name, start_limit_res) + } + + pub(crate) fn register_start_limit_result( +@@ -112,8 +102,7 @@ impl DataManager { + name: &str, + subscriber: Rc>, + ) -> Option>> { +- let mut table = self.tables.2.borrow_mut(); +- table.subscribe(name.to_string(), subscriber) ++ self.tables.2.subscribe(name.to_string(), subscriber) + } + + pub(crate) fn insert_job_result( +@@ -121,8 +110,7 @@ impl DataManager { + u_name: String, + job_result: JobResult, + ) -> Option { +- let mut table = self.tables.3.borrow_mut(); +- table.insert(u_name, job_result) ++ self.tables.3.insert(u_name, job_result) + } + + pub(crate) fn register_job_result( +@@ -130,19 +118,20 @@ impl DataManager { + name: &str, + subscriber: Rc>, + ) -> Option>> { +- let mut table = self.tables.3.borrow_mut(); +- table.subscribe(name.to_string(), subscriber) ++ self.tables.3.subscribe(name.to_string(), subscriber) + } + + // repeating protection + pub(crate) fn clear(&self) { +- self.tables.0.borrow_mut().clear(); +- self.tables.1.borrow_mut().clear(); ++ self.tables.0.clear(); ++ self.tables.1.clear(); + } + } + + #[cfg(test)] + mod tests { ++ use std::cell::RefCell; ++ + use super::*; + use crate::unit::UnitRelations; + use crate::utils::table::TableOp; +diff --git a/core/bin/unit/datastore/sets.rs b/core/bin/unit/datastore/sets.rs +index 677d21b..538df8f 100644 +--- a/core/bin/unit/datastore/sets.rs ++++ b/core/bin/unit/datastore/sets.rs +@@ -54,7 +54,7 @@ impl UnitSets { + } + + pub(super) fn get(&self, name: &str) -> Option> { +- self.t.borrow().get(&name.to_string()).cloned() ++ self.t.borrow().get(&name.to_string()) + } + + pub(super) fn get_all(&self) -> Vec> { +diff --git a/core/bin/unit/entry/ratelimit.rs b/core/bin/unit/entry/ratelimit.rs +index 2f2a446..2c67232 100644 +--- a/core/bin/unit/entry/ratelimit.rs ++++ b/core/bin/unit/entry/ratelimit.rs +@@ -17,7 +17,7 @@ pub(super) struct StartLimit { + start_limit: RefCell, + } + +-#[derive(PartialEq, Eq)] ++#[derive(PartialEq, Eq, Clone)] + pub(crate) enum StartLimitResult { + StartLimitNotHit, + StartLimitHit, +diff --git a/core/bin/utils/table.rs b/core/bin/utils/table.rs +index 90846cc..e1768d2 100644 +--- a/core/bin/utils/table.rs ++++ b/core/bin/utils/table.rs +@@ -10,6 +10,7 @@ + // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + // See the Mulan PSL v2 for more details. + ++use std::cell::RefCell; + use std::collections::HashMap; + use std::hash::Hash; + use std::rc::Rc; +@@ -30,47 +31,45 @@ pub trait TableSubscribe { + + //#[derive(Debug)] + pub struct Table { +- data: HashMap, // key + value +- subscribers: HashMap>>, // key: name, value: subscriber ++ data: RefCell>, // key + value ++ subscribers: RefCell>>>, // key: name, value: subscriber + } + + impl Table + where + K: Eq + Hash + Clone, ++ V: Clone, + { + pub fn new() -> Table { + Table { +- data: HashMap::new(), +- subscribers: HashMap::new(), ++ data: RefCell::new(HashMap::new()), ++ subscribers: RefCell::new(HashMap::new()), + } + } + +- pub fn data_clear(&mut self) { ++ pub fn data_clear(&self) { + // clear all data without notifying subscribers +- self.data.clear(); ++ self.data.borrow_mut().clear(); + } + +- pub fn clear(&mut self) { ++ pub fn clear(&self) { + // clear all, including data and subscribers + self.data_clear(); +- self.subscribers.clear(); ++ self.subscribers.borrow_mut().clear(); + } + +- pub fn insert(&mut self, k: K, v: V) -> Option { ++ pub fn insert(&self, k: K, v: V) -> Option { + let key = k.clone(); +- let ret = self.data.insert(k, v); +- let value = self +- .data +- .get(&key) +- .expect("something inserted is not found."); +- let op = TableOp::TableInsert(&key, value); ++ let ret = self.data.borrow_mut().insert(k, v); ++ let value = self.get(&key).expect("something inserted is not found."); ++ let op = TableOp::TableInsert(&key, &value); + self.notify(&op); + ret + } + + #[allow(dead_code)] +- pub fn remove(&mut self, k: &K) -> Option { +- let ret = self.data.remove(k); ++ pub fn remove(&self, k: &K) -> Option { ++ let ret = self.data.borrow_mut().remove(k); + if let Some(v) = &ret { + let op = TableOp::TableRemove(k, v); + self.notify(&op); +@@ -78,29 +77,33 @@ where + ret + } + +- pub fn get(&self, k: &K) -> Option<&V> { +- self.data.get(k) ++ pub fn get(&self, k: &K) -> Option { ++ self.data.borrow().get(k).cloned() + } + +- pub fn get_all(&self) -> Vec<&V> { +- self.data.values().collect::>() ++ pub fn get_all(&self) -> Vec { ++ self.data ++ .borrow() ++ .values() ++ .map(|v| v.clone()) ++ .collect::>() + } + + pub fn subscribe( +- &mut self, ++ &self, + name: String, + subscriber: Rc>, + ) -> Option>> { +- self.subscribers.insert(name, subscriber) ++ self.subscribers.borrow_mut().insert(name, subscriber) + } + + #[allow(dead_code)] +- pub fn unsubscribe(&mut self, name: &str) -> Option>> { +- self.subscribers.remove(name) ++ pub fn unsubscribe(&self, name: &str) -> Option>> { ++ self.subscribers.borrow_mut().remove(name) + } + + fn notify(&self, op: &TableOp<'_, K, V>) { +- for (_, subscriber) in self.subscribers.iter() { ++ for (_, subscriber) in self.subscribers.borrow().iter() { + if subscriber.filter(op) { + subscriber.notify(op); + } +@@ -115,7 +118,7 @@ mod tests { + + #[test] + fn table_insert() { +- let mut table: Table = Table::new(); ++ let table: Table = Table::new(); + + let old = table.insert(1, 'a'); + assert_eq!(old, None); +@@ -129,7 +132,7 @@ mod tests { + + #[test] + fn table_remove() { +- let mut table: Table = Table::new(); ++ let table: Table = Table::new(); + + let old = table.remove(&1); + assert_eq!(old, None); +@@ -148,25 +151,25 @@ mod tests { + + #[test] + fn table_get() { +- let mut table: Table = Table::new(); ++ let table: Table = Table::new(); + + let value = table.get(&1); + assert_eq!(value, None); + + table.insert(1, 'a'); + let value = table.get(&1); +- assert_eq!(value.cloned(), Some('a')); ++ assert_eq!(value, Some('a')); + let value = table.get(&2); + assert_eq!(value, None); + + table.insert(2, 'b'); + let value = table.get(&2); +- assert_eq!(value.cloned(), Some('b')); ++ assert_eq!(value, Some('b')); + } + + #[test] + fn table_subscribe() { +- let mut table: Table = Table::new(); ++ let table: Table = Table::new(); + let sub_test1 = Rc::new(TableTest::new()); + let sub_test2 = Rc::new(TableTest::new()); + +@@ -185,7 +188,7 @@ mod tests { + + #[test] + fn table_unsubscribe() { +- let mut table: Table = Table::new(); ++ let table: Table = Table::new(); + let sub_test1 = Rc::new(TableTest::new()); + let sub_test2 = Rc::new(TableTest::new()); + +@@ -209,7 +212,7 @@ mod tests { + + #[test] + fn table_notify() { +- let mut table: Table = Table::new(); ++ let table: Table = Table::new(); + let sub_test1 = Rc::new(TableTest::new()); + let sub_test2 = Rc::new(TableTest::new()); + +-- +2.30.2 + diff --git a/backport-fix-only-remove-one-unit-s-pid-from-db-PR-568-remove.patch b/backport-fix-only-remove-one-unit-s-pid-from-db-PR-568-remove.patch new file mode 100644 index 0000000..915d2d6 --- /dev/null +++ b/backport-fix-only-remove-one-unit-s-pid-from-db-PR-568-remove.patch @@ -0,0 +1,52 @@ +From 8e872af3529d75a05fad98824786415045c8cf10 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 15:57:55 +0800 +Subject: [PATCH] fix: only remove one unit's pid from db PR #568 removes all + unit's pids when one unit enters dead state, which is definitely wrong. We + should only remove one unit's pid from db, and other unit's pids should still + be watched. + +--- + core/bin/unit/datastore/child.rs | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/core/bin/unit/datastore/child.rs b/core/bin/unit/datastore/child.rs +index 60c73c5..f4460f0 100644 +--- a/core/bin/unit/datastore/child.rs ++++ b/core/bin/unit/datastore/child.rs +@@ -59,7 +59,7 @@ impl UnitChild { + } + + pub(super) fn add_watch_pid(&self, id: &str, pid: Pid) { +- log::debug!("borrow add watch_pids for pid:{}, id:{}", pid, id); ++ log::debug!("Adding watch_pids {} to {}", pid, id); + let unit = self.units.get(id).unwrap(); + self.data.add_watch_pid(unit.clone(), pid); + unit.child_add_pids(pid); +@@ -67,17 +67,19 @@ impl UnitChild { + + pub(super) fn unwatch_pid(&self, id: &str, pid: Pid) { + let unit = self.units.get(id).unwrap(); +- log::debug!("borrow remove watch_pids for {}", pid); ++ log::debug!("Removing watch_pids {} from {}", pid, id); + self.data.unwatch_pid(unit.clone(), pid); + unit.child_remove_pids(pid); + } + + pub(super) fn unwatch_all_pids(&self, id: &str) { ++ log::debug!("Unwatching all watch_pids of {}", id); + let unit = self.units.get(id).unwrap(); +- for i in self.data.watch_pids.borrow().keys() { +- unit.child_remove_pids(*i); ++ let delete_pids = unit.get_pids(); ++ for pid in delete_pids { ++ unit.child_remove_pids(pid); ++ self.data.unwatch_pid(unit.clone(), pid); + } +- self.data.watch_pids.borrow_mut().clear(); + } + + pub(super) fn get_unit_by_pid(&self, pid: Pid) -> Option> { +-- +2.30.2 + diff --git a/backport-fix-really-use-usec.patch b/backport-fix-really-use-usec.patch new file mode 100644 index 0000000..dcd9263 --- /dev/null +++ b/backport-fix-really-use-usec.patch @@ -0,0 +1,79 @@ +From a9134b19fc0c942f842a7b51a956347951c89f8b Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 14 Jun 2023 17:24:08 +0800 +Subject: [PATCH] fix: really use usec + +watchdog_usec was actually watchdog_sec formerly +--- + coms/service/src/mng.rs | 14 +++++++------- + coms/service/src/spawn.rs | 2 +- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/coms/service/src/mng.rs b/coms/service/src/mng.rs +index 5c71531..bfa2c9f 100644 +--- a/coms/service/src/mng.rs ++++ b/coms/service/src/mng.rs +@@ -1233,9 +1233,9 @@ impl ServiceMng { + } + + fn restart_watchdog(&self) { +- self.monitor +- .borrow_mut() +- .set_original_watchdog(self.config.config_data().borrow().Service.WatchdogSec); ++ self.monitor.borrow_mut().set_original_watchdog( ++ self.config.config_data().borrow().Service.WatchdogSec * 1000000, ++ ); + let watchdog_usec = self.monitor.borrow().watchdog_usec(); + if watchdog_usec == 0 || watchdog_usec == u64::MAX { + self.stop_watchdog(); +@@ -2455,7 +2455,7 @@ impl Source for ServiceTimer { + struct ServiceMonitorData { + mng: RefCell>, + // owned objects +- time: RefCell, ++ time: RefCell, /* usec */ + } + + // the declaration "pub(self)" is for identification only. +@@ -2511,7 +2511,7 @@ impl Source for ServiceMonitorData { + } + + fn time_relative(&self) -> u64 { +- *self.time.borrow() * 1000000 ++ *self.time.borrow() + } + + fn dispatch(&self, _: &Events) -> i32 { +@@ -2575,7 +2575,7 @@ mod tests { + assert!(rt.armd_watchdog()); + assert_eq!( + rt.watchdog().time(), +- config.config_data().borrow().Service.WatchdogSec ++ config.config_data().borrow().Service.WatchdogSec * 1000000 + ); + } + +@@ -2594,7 +2594,7 @@ mod tests { + assert!(rt.armd_watchdog()); + assert_eq!( + rt.watchdog().time(), +- config.config_data().borrow().Service.WatchdogSec ++ config.config_data().borrow().Service.WatchdogSec * 1000000 + ); + + messages.remove("WATCHDOG"); +diff --git a/coms/service/src/spawn.rs b/coms/service/src/spawn.rs +index 9b895aa..2ff9e92 100644 +--- a/coms/service/src/spawn.rs ++++ b/coms/service/src/spawn.rs +@@ -164,6 +164,6 @@ impl ServiceSpawn { + } + + fn watchdog_timer(&self) -> u64 { +- self.config.config_data().borrow().Service.WatchdogSec ++ self.config.config_data().borrow().Service.WatchdogSec * 1000000 + } + } +-- +2.30.2 + diff --git a/backport-fix-remove-some-debug-message-no-functional-change.patch b/backport-fix-remove-some-debug-message-no-functional-change.patch new file mode 100644 index 0000000..776b263 --- /dev/null +++ b/backport-fix-remove-some-debug-message-no-functional-change.patch @@ -0,0 +1,78 @@ +From c7600975afe9a2b13d33c10cc081e5de4b0d8270 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 10:51:33 +0800 +Subject: [PATCH 1/9] fix: remove some debug message, no functional change + +--- + coms/socket/src/mng.rs | 2 -- + core/bin/unit/notify.rs | 2 -- + libs/event/tests/inotify.rs | 1 - + libs/event/tests/io.rs | 1 - + libs/event/tests/signal.rs | 1 - + 5 files changed, 7 deletions(-) + +diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs +index e7a6a01..33b9812 100644 +--- a/coms/socket/src/mng.rs ++++ b/coms/socket/src/mng.rs +@@ -848,8 +848,6 @@ impl Source for SocketMngPort { + } + + fn dispatch(&self, _: &Events) -> i32 { +- println!("Dispatching IO!"); +- + self.reli().set_last_frame2( + ReliLastFrame::SubManager as u32, + UnitType::UnitSocket as u32, +diff --git a/core/bin/unit/notify.rs b/core/bin/unit/notify.rs +index cb05330..f824725 100644 +--- a/core/bin/unit/notify.rs ++++ b/core/bin/unit/notify.rs +@@ -332,8 +332,6 @@ impl Source for Notify { + } + + fn dispatch(&self, _e: &Events) -> i32 { +- log::debug!("begin to dispatch notify event"); +- + self.reli.set_last_frame1(ReliLastFrame::Notify as u32); + let ret = self.notify_dispatch(); + self.reli.clear_last_frame(); +diff --git a/libs/event/tests/inotify.rs b/libs/event/tests/inotify.rs +index 5fb3f5f..e9bdf72 100644 +--- a/libs/event/tests/inotify.rs ++++ b/libs/event/tests/inotify.rs +@@ -49,7 +49,6 @@ mod test { + } + + fn dispatch(&self, e: &Events) -> i32 { +- println!("Dispatching inotify!"); + e.set_exit(); + 0 + } +diff --git a/libs/event/tests/io.rs b/libs/event/tests/io.rs +index 292ed16..be79494 100644 +--- a/libs/event/tests/io.rs ++++ b/libs/event/tests/io.rs +@@ -54,7 +54,6 @@ mod test { + } + + fn dispatch(&self, _: &Events) -> i32 { +- println!("Dispatching IO!"); + 0 + } + +diff --git a/libs/event/tests/signal.rs b/libs/event/tests/signal.rs +index 3a54812..961bd5a 100644 +--- a/libs/event/tests/signal.rs ++++ b/libs/event/tests/signal.rs +@@ -47,7 +47,6 @@ impl Source for Signals { + } + + fn dispatch(&self, e: &Events) -> i32 { +- println!("Dispatching signal!"); + match e.read_signals() { + Ok(Some(info)) => { + println!("read signo: {:?}", info.ssi_signo); +-- +2.30.2 + diff --git a/backport-fix-unwatch-all-pids-when-the-service-enters-dead.patch b/backport-fix-unwatch-all-pids-when-the-service-enters-dead.patch new file mode 100644 index 0000000..a00cee7 --- /dev/null +++ b/backport-fix-unwatch-all-pids-when-the-service-enters-dead.patch @@ -0,0 +1,145 @@ +From c38d3c9dd677b28cbdd638b853475f74c42936bf Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Mon, 22 May 2023 11:56:18 +0800 +Subject: [PATCH] fix: unwatch all pids when the service enters dead + +--- + coms/service/src/mng.rs | 10 ++++++++++ + coms/service/src/pid.rs | 6 ++++++ + core/bin/unit/datastore/child.rs | 18 ++++++++++++------ + core/bin/unit/datastore/mod.rs | 4 ++++ + core/bin/unit/manager.rs | 9 +++++++++ + core/lib/unit/umif.rs | 3 +++ + 6 files changed, 44 insertions(+), 6 deletions(-) + +diff --git a/coms/service/src/mng.rs b/coms/service/src/mng.rs +index dff610e..d73fa34 100644 +--- a/coms/service/src/mng.rs ++++ b/coms/service/src/mng.rs +@@ -845,6 +845,16 @@ impl ServiceMng { + self.set_cmd_type(None); + } + ++ if vec![ ++ ServiceState::Dead, ++ ServiceState::Failed, ++ ServiceState::AutoRestart, ++ ] ++ .contains(&state) ++ { ++ self.pid.child_unwatch_all_pids(); ++ } ++ + // todo!() + // trigger the unit the dependency trigger_by + +diff --git a/coms/service/src/pid.rs b/coms/service/src/pid.rs +index deba828..a25de50 100644 +--- a/coms/service/src/pid.rs ++++ b/coms/service/src/pid.rs +@@ -94,6 +94,12 @@ impl ServicePid { + } + } + ++ pub(super) fn child_unwatch_all_pids(&self) { ++ if let Some(u) = self.comm.owner() { ++ self.comm.um().child_unwatch_all_pids(u.id()); ++ } ++ } ++ + pub(super) fn main(&self) -> Option { + self.data.borrow().main() + } +diff --git a/core/bin/unit/datastore/child.rs b/core/bin/unit/datastore/child.rs +index fd8fffa..af63792 100644 +--- a/core/bin/unit/datastore/child.rs ++++ b/core/bin/unit/datastore/child.rs +@@ -57,17 +57,23 @@ impl UnitChild { + pub(super) fn add_watch_pid(&self, id: &str, pid: Pid) { + log::debug!("borrow add watch_pids for pid:{}, id:{}", pid, id); + let unit = self.units.get(id).unwrap(); +- let u = Rc::clone(&unit); +- self.data.add_watch_pid(unit, pid); +- u.child_add_pids(pid); ++ self.data.add_watch_pid(unit.clone(), pid); ++ unit.child_add_pids(pid); + } + + pub(super) fn unwatch_pid(&self, id: &str, pid: Pid) { + let unit = self.units.get(id).unwrap(); +- let u = Rc::clone(&unit); + log::debug!("borrow remove watch_pids for {}", pid); +- self.data.unwatch_pid(unit, pid); +- u.child_remove_pids(pid); ++ self.data.unwatch_pid(unit.clone(), pid); ++ unit.child_remove_pids(pid); ++ } ++ ++ pub(super) fn unwatch_all_pids(&self, id: &str) { ++ let unit = self.units.get(id).unwrap(); ++ for i in self.data.watch_pids.borrow().keys() { ++ unit.child_remove_pids(*i); ++ } ++ self.data.watch_pids.borrow_mut().clear(); + } + + pub(super) fn get_unit_by_pid(&self, pid: Pid) -> Option> { +diff --git a/core/bin/unit/datastore/mod.rs b/core/bin/unit/datastore/mod.rs +index d3f8839..1dc09d7 100644 +--- a/core/bin/unit/datastore/mod.rs ++++ b/core/bin/unit/datastore/mod.rs +@@ -160,6 +160,10 @@ impl UnitDb { + } + } + ++ pub fn child_unwatch_all_pids(&self, id: &str) { ++ self.child.unwatch_all_pids(id); ++ } ++ + pub fn get_unit_by_pid(&self, pid: Pid) -> Option> { + self.child.get_unit_by_pid(pid) + } +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 0677c1b..bee3093 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -392,6 +392,10 @@ impl UmIf for UnitManager { + self.child_watch_all_pids(id) + } + ++ fn child_unwatch_all_pids(&self, id: &str) { ++ self.child_unwatch_all_pids(id) ++ } ++ + fn notify_socket(&self) -> Option { + self.notify_socket() + } +@@ -480,6 +484,11 @@ impl UnitManager { + self.db.child_watch_all_pids(id) + } + ++ /// remove all pids ++ fn child_unwatch_all_pids(&self, id: &str) { ++ self.db.child_unwatch_all_pids(id) ++ } ++ + /// delete the pid from the db + fn child_unwatch_pid(&self, id: &str, pid: Pid) { + self.db.child_unwatch_pid(id, pid) +diff --git a/core/lib/unit/umif.rs b/core/lib/unit/umif.rs +index 027c59f..4821ff9 100644 +--- a/core/lib/unit/umif.rs ++++ b/core/lib/unit/umif.rs +@@ -134,6 +134,9 @@ pub trait UmIf { + /// add all the pid of unit id, read pids from cgroup path. + fn child_watch_all_pids(&self, _id: &str) {} + ++ /// remove all the pid of unit id ++ fn child_unwatch_all_pids(&self, _id: &str) {} ++ + ///rentry_trigger_merge + fn rentry_trigger_merge(&self, _unit_id: &str, _force: bool) {} + +-- +2.30.2 + diff --git a/backport-refactor-rename-UNitNotifyFlags-to-shorten-code-a-bi.patch b/backport-refactor-rename-UNitNotifyFlags-to-shorten-code-a-bi.patch new file mode 100644 index 0000000..f727dfe --- /dev/null +++ b/backport-refactor-rename-UNitNotifyFlags-to-shorten-code-a-bi.patch @@ -0,0 +1,189 @@ +From 95210185215c933fa00be50c96505ef390df349c Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 31 May 2023 10:57:10 +0800 +Subject: [PATCH 2/9] refactor: rename UNitNotifyFlags to shorten code a bit + change UNIT_NOTIFY_SUCCESS to EMPTY, the original SUCCESS doesn't make sense + +--- + coms/mount/src/mng.rs | 2 +- + coms/service/src/mng.rs | 6 +++--- + coms/socket/src/mng.rs | 2 +- + coms/target/src/mng.rs | 2 +- + core/bin/job/entry.rs | 2 +- + core/bin/job/manager.rs | 5 ++--- + core/bin/unit/data/table.rs | 2 +- + core/bin/unit/entry/uentry.rs | 6 +----- + core/bin/unit/manager.rs | 1 - + core/lib/unit/state.rs | 8 ++++---- + 10 files changed, 15 insertions(+), 21 deletions(-) + +diff --git a/coms/mount/src/mng.rs b/coms/mount/src/mng.rs +index e09d1f7..5383c4d 100644 +--- a/coms/mount/src/mng.rs ++++ b/coms/mount/src/mng.rs +@@ -108,7 +108,7 @@ impl MountMng { + u.notify( + old_unit_state, + new_unit_state, +- UnitNotifyFlags::UNIT_NOTIFY_RELOAD_FAILURE, ++ UnitNotifyFlags::RELOAD_FAILURE, + ) + } + +diff --git a/coms/service/src/mng.rs b/coms/service/src/mng.rs +index 0f5db5f..fa6237a 100644 +--- a/coms/service/src/mng.rs ++++ b/coms/service/src/mng.rs +@@ -862,14 +862,14 @@ impl ServiceMng { + let os = service_state_to_unit_state(self.config.service_type(), original_state); + let ns = service_state_to_unit_state(self.config.service_type(), state); + if let Some(u) = self.comm.owner() { +- let mut flags = UnitNotifyFlags::UNIT_NOTIFY_SUCCESS; ++ let mut flags = UnitNotifyFlags::EMPTY; + + if self.rd.will_auto_restart() { +- flags |= UnitNotifyFlags::UNIT_NOTIFY_WILL_AUTO_RESTART; ++ flags |= UnitNotifyFlags::WILL_AUTO_RESTART; + } + + if self.reload_result() != ServiceResult::Success { +- flags |= UnitNotifyFlags::UNIT_NOTIFY_RELOAD_FAILURE; ++ flags |= UnitNotifyFlags::RELOAD_FAILURE; + } + u.notify(os, ns, flags) + } +diff --git a/coms/socket/src/mng.rs b/coms/socket/src/mng.rs +index 33b9812..fe77517 100644 +--- a/coms/socket/src/mng.rs ++++ b/coms/socket/src/mng.rs +@@ -650,7 +650,7 @@ impl SocketMng { + u.notify( + original_state.to_unit_active_state(), + state.to_unit_active_state(), +- UnitNotifyFlags::UNIT_NOTIFY_RELOAD_FAILURE, ++ UnitNotifyFlags::RELOAD_FAILURE, + ) + } + } +diff --git a/coms/target/src/mng.rs b/coms/target/src/mng.rs +index 039fa9e..dc52339 100644 +--- a/coms/target/src/mng.rs ++++ b/coms/target/src/mng.rs +@@ -112,7 +112,7 @@ impl TargetMng { + unit.notify( + old_unit_state, + new_unit_state, +- UnitNotifyFlags::UNIT_NOTIFY_RELOAD_FAILURE, ++ UnitNotifyFlags::RELOAD_FAILURE, + ); + + self.db_update(); +diff --git a/core/bin/job/entry.rs b/core/bin/job/entry.rs +index 54af665..81f443a 100755 +--- a/core/bin/job/entry.rs ++++ b/core/bin/job/entry.rs +@@ -621,7 +621,7 @@ fn job_process_unit_reload( + flags: UnitNotifyFlags, + ) -> (Option, bool) { + let mut result = JobResult::Done; +- if flags.intersects(UnitNotifyFlags::UNIT_NOTIFY_RELOAD_FAILURE) { ++ if flags.intersects(UnitNotifyFlags::RELOAD_FAILURE) { + result = JobResult::Failed; + } + match ns { +diff --git a/core/bin/job/manager.rs b/core/bin/job/manager.rs +index e8eee8b..028c4d5 100755 +--- a/core/bin/job/manager.rs ++++ b/core/bin/job/manager.rs +@@ -268,7 +268,6 @@ impl Source for JobManagerData { + + fn dispatch(&self, _event: &Events) -> i32 { + log::debug!("job manager data dispatch"); +- + self.reli.set_last_frame1(ReliLastFrame::JobManager as u32); + self.run(None); + self.reli.clear_last_frame(); +@@ -728,7 +727,7 @@ impl JobManagerData { + ) { + // OnFailure= + if ns != os +- && !flags.intersects(UnitNotifyFlags::UNIT_NOTIFY_WILL_AUTO_RESTART) ++ && !flags.intersects(UnitNotifyFlags::WILL_AUTO_RESTART) + && ns == UnitActiveState::UnitFailed + { + let job_mode = unit +@@ -746,7 +745,7 @@ impl JobManagerData { + + // OnSuccess= + if ns == UnitActiveState::UnitInActive +- && !flags.intersects(UnitNotifyFlags::UNIT_NOTIFY_WILL_AUTO_RESTART) ++ && !flags.intersects(UnitNotifyFlags::WILL_AUTO_RESTART) + { + match os { + UnitActiveState::UnitFailed +diff --git a/core/bin/unit/data/table.rs b/core/bin/unit/data/table.rs +index cfacf80..480a026 100644 +--- a/core/bin/unit/data/table.rs ++++ b/core/bin/unit/data/table.rs +@@ -178,7 +178,7 @@ mod tests { + let dm = DataManager::new(); + let os = UnitActiveState::UnitInActive; + let ns = UnitActiveState::UnitActive; +- let flags = UnitNotifyFlags::UNIT_NOTIFY_RELOAD_FAILURE; ++ let flags = UnitNotifyFlags::RELOAD_FAILURE; + let us_sub = Rc::new(UnitStatesTest::new(ns)); + + let old = dm.insert_unit_state(String::from("test"), UnitState::new(os, ns, flags)); +diff --git a/core/bin/unit/entry/uentry.rs b/core/bin/unit/entry/uentry.rs +index a22ad10..307240b 100644 +--- a/core/bin/unit/entry/uentry.rs ++++ b/core/bin/unit/entry/uentry.rs +@@ -694,11 +694,7 @@ impl Unit { + Ok(_) => Ok(()), + Err(e) => match e { + Error::UnitActionEOpNotSupp => { +- self.notify( +- active_state, +- active_state, +- UnitNotifyFlags::UNIT_NOTIFY_SUCCESS, +- ); ++ self.notify(active_state, active_state, UnitNotifyFlags::EMPTY); + Ok(()) + } + _ => Err(e), +diff --git a/core/bin/unit/manager.rs b/core/bin/unit/manager.rs +index 6e83240..d5c3e10 100644 +--- a/core/bin/unit/manager.rs ++++ b/core/bin/unit/manager.rs +@@ -1051,7 +1051,6 @@ impl UnitManager { + if let Err(_e) = self.jm.try_finish(&unitx, state.os, state.ns, state.flags) { + // debug + } +- + let atom = UnitRelationAtom::UnitAtomTriggeredBy; + for other in self.db.dep_gets_atom(&unitx, atom) { + other.trigger(&unitx); +diff --git a/core/lib/unit/state.rs b/core/lib/unit/state.rs +index d5e204a..1ae747b 100644 +--- a/core/lib/unit/state.rs ++++ b/core/lib/unit/state.rs +@@ -102,12 +102,12 @@ impl std::fmt::Display for UnitActiveState { + bitflags! { + /// notify unit state to manager + pub struct UnitNotifyFlags: u8 { +- /// the default flags propagate to jobs, it meas nothing. +- const UNIT_NOTIFY_SUCCESS = 0; ++ /// the default flags propagate to jobs, it means nothing. ++ const EMPTY = 0; + /// notify that the unit running reload failure +- const UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0; ++ const RELOAD_FAILURE = 1 << 0; + /// notify that the unit is in auto restart state +- const UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1; ++ const WILL_AUTO_RESTART = 1 << 1; + } + } + +-- +2.30.2 + diff --git a/backport-refactor-use-UnixStream-instead-TcpListener-to-get-t.patch b/backport-refactor-use-UnixStream-instead-TcpListener-to-get-t.patch new file mode 100644 index 0000000..88aebf8 --- /dev/null +++ b/backport-refactor-use-UnixStream-instead-TcpListener-to-get-t.patch @@ -0,0 +1,141 @@ +From 95ccf8bc7738d23844411a3770d95dd702cdabb1 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Thu, 1 Jun 2023 15:37:11 +0800 +Subject: [PATCH] refactor: use UnixStream instead TcpListener to get the + message from sctl + +--- + core/bin/manager/commands.rs | 37 ++++++++++++++++++++++++++---------- + exts/sctl/Cargo.toml | 1 + + exts/sctl/src/main.rs | 15 ++++----------- + libs/constants/src/lib.rs | 3 +++ + 4 files changed, 35 insertions(+), 21 deletions(-) + +diff --git a/core/bin/manager/commands.rs b/core/bin/manager/commands.rs +index d6ef907..1279206 100644 +--- a/core/bin/manager/commands.rs ++++ b/core/bin/manager/commands.rs +@@ -13,32 +13,49 @@ + use cmdproto::proto::execute::ExecuterAction; + use cmdproto::proto::ProstServerStream; + use event::{EventType, Events, Source}; +-use std::net::{SocketAddr, TcpListener}; ++use nix::sys::{socket, stat}; + use std::os::unix::io::RawFd; ++use std::path::Path; + use std::{os::unix::prelude::AsRawFd, rc::Rc}; + use sysmaster::rel::{ReliLastFrame, Reliability}; + ++use constants::SCTL_SOCKET; ++ + pub(super) struct Commands { + // associated objects + reli: Rc, + command_action: Rc, + + // owned objects +- fd: TcpListener, ++ socket_fd: i32, + } + + impl Commands { + pub(super) fn new(relir: &Rc, comm_action: T) -> Self { +- let addrs = [ +- SocketAddr::from(([127, 0, 0, 1], 9526)), +- SocketAddr::from(([127, 0, 0, 1], 9527)), +- ]; +- let fd = TcpListener::bind(&addrs[..]).unwrap(); +- fd.set_nonblocking(true).expect("set non-blocking"); ++ let sctl_socket_path = Path::new(SCTL_SOCKET); ++ /* remove the old socket if it exists */ ++ if sctl_socket_path.exists() && !sctl_socket_path.is_symlink() { ++ let _ = std::fs::remove_file(sctl_socket_path); ++ } ++ let sctl_socket_addr = socket::UnixAddr::new(Path::new(SCTL_SOCKET)).unwrap(); ++ let socket_fd = socket::socket( ++ socket::AddressFamily::Unix, ++ socket::SockType::Stream, ++ socket::SockFlag::empty(), ++ None, ++ ) ++ .unwrap(); ++ /* create the socket with mode 666 */ ++ let old_mask = stat::umask(stat::Mode::from_bits_truncate(!0o666)); ++ let _ = socket::bind(socket_fd, &sctl_socket_addr); ++ /* restore our umask */ ++ let _ = stat::umask(old_mask); ++ /* Allow at most 10 incomming connections can queue */ ++ let _ = socket::listen(socket_fd, 10); + Commands { + reli: Rc::clone(relir), + command_action: Rc::new(comm_action), +- fd, ++ socket_fd, + } + } + } +@@ -83,7 +100,7 @@ where + } + + fn fd(&self) -> RawFd { +- self.fd.as_raw_fd() ++ self.socket_fd.as_raw_fd() + } + + fn priority(&self) -> i8 { +diff --git a/exts/sctl/Cargo.toml b/exts/sctl/Cargo.toml +index 775bc85..b0c0bfc 100644 +--- a/exts/sctl/Cargo.toml ++++ b/exts/sctl/Cargo.toml +@@ -10,3 +10,4 @@ clap = { version = "3.1.8", features = ["derive"] } + cmdproto = { path = "../../libs/cmdproto" } + basic = { path = "../../libs/basic" } + nix = "0.24" ++constants = { version = "0.1.0", path = "../../libs/constants" } +diff --git a/exts/sctl/src/main.rs b/exts/sctl/src/main.rs +index ef360c7..c6d9281 100644 +--- a/exts/sctl/src/main.rs ++++ b/exts/sctl/src/main.rs +@@ -17,11 +17,9 @@ use cmdproto::proto::{ + abi::{sys_comm, unit_comm, CommandRequest}, + mngr_comm, unit_file, ProstClientStream, + }; +-use std::io::Write; +-use std::{ +- net::{SocketAddr, TcpStream}, +- process::exit, +-}; ++use constants::SCTL_SOCKET; ++use std::process::exit; ++use std::{io::Write, os::unix::net::UnixStream}; + + /// parse program arguments + #[derive(Parser, Debug)] +@@ -195,12 +193,7 @@ fn main() { + Some(v) => v, + }; + +- let addrs = [ +- SocketAddr::from(([127, 0, 0, 1], 9526)), +- SocketAddr::from(([127, 0, 0, 1], 9527)), +- ]; +- +- let stream = match TcpStream::connect(&addrs[..]) { ++ let stream = match UnixStream::connect(SCTL_SOCKET) { + Err(e) => { + eprintln!("Failed to connect to sysmaster: {}", e); + exit(e.raw_os_error().unwrap() as i32); +diff --git a/libs/constants/src/lib.rs b/libs/constants/src/lib.rs +index bd3fba2..7c918aa 100644 +--- a/libs/constants/src/lib.rs ++++ b/libs/constants/src/lib.rs +@@ -25,3 +25,6 @@ pub const SIG_SWITCH_ROOT_OFFSET: i32 = 10; + pub const INIT_SOCKET: &str = "/run/sysmaster/init"; + /// sysmaster send this to init to keep alive + pub const ALIVE: &str = "ALIVE01234567890"; ++ ++/// Socket used to transfer message between sysmaster and sctl ++pub const SCTL_SOCKET: &str = "/run/sysmaster/sctl"; +-- +2.30.2 + diff --git a/backport-typo-fix-some-typoes-no-functional-change.patch b/backport-typo-fix-some-typoes-no-functional-change.patch new file mode 100644 index 0000000..678ef60 --- /dev/null +++ b/backport-typo-fix-some-typoes-no-functional-change.patch @@ -0,0 +1,25 @@ +From e5368bb7b9c2681f802993f0225e832d5e647b70 Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Fri, 2 Jun 2023 14:11:24 +0800 +Subject: [PATCH] typo: fix some typoes, no functional change + +--- + core/bin/manager/commands.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/core/bin/manager/commands.rs b/core/bin/manager/commands.rs +index a8320e2..5eeb927 100644 +--- a/core/bin/manager/commands.rs ++++ b/core/bin/manager/commands.rs +@@ -50,7 +50,7 @@ impl Commands { + let _ = socket::bind(socket_fd, &sctl_socket_addr); + /* restore our umask */ + let _ = stat::umask(old_mask); +- /* Allow at most 10 incomming connections can queue */ ++ /* Allow at most 10 incoming connections can queue */ + let _ = socket::listen(socket_fd, 10); + Commands { + reli: Rc::clone(relir), +-- +2.30.2 + diff --git a/sysmaster.spec b/sysmaster.spec index 0ab2805..f8550e1 100644 --- a/sysmaster.spec +++ b/sysmaster.spec @@ -11,14 +11,40 @@ Name: sysmaster Version: 0.2.3 -Release: 2 +Release: 3 Summary: redesign and reimplement process1. License: Mulan PSL v2 URL: https://gitee.com/openeuler/sysmaster Source0: %{name}-%{version}.tar.gz -Patch0001: backport-fix-compatible-with-rustc-1.60.patch +Patch6000: backport-fix-check-if-the-returned-state-is-None.patch +Patch6001: backport-fix-unwatch-all-pids-when-the-service-enters-dead.patch +Patch6002: backport-fix-only-remove-one-unit-s-pid-from-db-PR-568-remove.patch + +# Patch6003-Patch6011: https://gitee.com/openeuler/sysmaster/pulls/585 +Patch6003: backport-fix-remove-some-debug-message-no-functional-change.patch +Patch6004: backport-refactor-rename-UNitNotifyFlags-to-shorten-code-a-bi.patch +Patch6005: backport-feature-add-as_any-to-SubUnit-so-we-can-downcast-Sub.patch +Patch6006: backport-fix-move-RefCell-to-the-inside-of-Table-no-functiona.patch +Patch6007: backport-fix-add-has_source-to-events-and-use-this-in-socket..patch +Patch6008: backport-fix-change-if-port.fd-is-valid-we-should-avoid-deali.patch +Patch6009: backport-fix-enable-trigger-for-socket-and-use-this-interface.patch +Patch6010: backport-fix-change-the-socket-logic-to-keep-the-same-as-syst.patch +Patch6011: backport-fix-fix-some-cargo-clippies.patch +Patch6012: backport-fix-compatible-with-rustc-1.60.patch +Patch6013: backport-fix-compatible-with-rusc-1.60-lint-check.patch + +#Patch6014-Patch6016: https://gitee.com/openeuler/sysmaster/pulls/598 +Patch6014: backport-refactor-use-UnixStream-instead-TcpListener-to-get-t.patch +Patch6015: backport-feature-get-credential-from-the-connection-and-use-i.patch +Patch6016: backport-typo-fix-some-typoes-no-functional-change.patch + +Patch6017: backport-fix-fstab-use-fixed-inotify-version-0.10.0-to-be-com.patch +Patch6018: backport-fix-don-t-mount-all-subsystem-to-every-sys-fs-cgroup.patch +Patch6019: backport-fix-check-if-the-given-unit-name-is-valid-before-we-.patch +Patch6020: backport-fix-really-use-usec.patch +Patch6021: backport-docs-note-that-we-only-support-no-more-than-500-unit.patch ExclusiveArch: x86_64 aarch64 @@ -73,6 +99,9 @@ install -Dm0640 -t %{sysmaster_install_target}/plugin %{conf_install_source}/plu /usr/lib/sysmaster/* %changelog +* Fri Jun 16 2023 licunlong - 0.2.3-3 +- sync patches from upstream + * Tue May 30 2023 shenyangyang - 0.2.3-2 - Support compatible compile with rust 1.60