From 25ed3dc98b47a2e3f3dd5b199fcfa23715a4acb3 Mon Sep 17 00:00:00 2001 From: licunlong Date: Thu, 7 Dec 2023 11:54:04 +0800 Subject: [PATCH 1/5] feature: this is a big step to move to systemd --- Cargo.lock | 1 + core/coms/mount/Cargo.toml | 1 + core/coms/mount/src/config.rs | 88 ++++++++- core/coms/mount/src/manager.rs | 5 +- core/coms/mount/src/mng.rs | 231 +++++++++++++++++++++--- core/coms/mount/src/rentry.rs | 35 ++++ core/coms/mount/src/unit.rs | 41 +++-- core/coms/service/src/rentry.rs | 10 +- core/coms/socket/src/rentry.rs | 2 + core/libcore/src/unit/base.rs | 2 +- core/libcore/src/unit/umif.rs | 2 +- core/sysmaster/src/unit/entry/uentry.rs | 6 +- core/sysmaster/src/unit/manager.rs | 13 +- 13 files changed, 371 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60c6b30e..73ea1a30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1122,6 +1122,7 @@ name = "mount" version = "0.5.1" dependencies = [ "basic", + "bitflags", "constants", "core", "epoll", diff --git a/core/coms/mount/Cargo.toml b/core/coms/mount/Cargo.toml index 80f336a9..7128d823 100644 --- a/core/coms/mount/Cargo.toml +++ b/core/coms/mount/Cargo.toml @@ -20,6 +20,7 @@ macros = { path = "../../../libs/macros" } constants = { path = "../../../libs/constants", optional = true } unit_parser = { path = "../../../libs/unit_parser" } +bitflags = { version = "1.3.2" } epoll = "=4.3.1" libc = { version = "0.2.*", default-features = false } nix = { version = "0.24", default-features = false, features = [ diff --git a/core/coms/mount/src/config.rs b/core/coms/mount/src/config.rs index 1bad5dde..074deaff 100644 --- a/core/coms/mount/src/config.rs +++ b/core/coms/mount/src/config.rs @@ -11,8 +11,11 @@ // See the Mulan PSL v2 for more details. // -use std::{cell::RefCell, path::PathBuf, rc::Rc}; +use core::error::Result; +use core::unit::KillContext; +use std::{cell::RefCell, path::PathBuf, rc::Rc, str::FromStr}; +use nix::sys::signal::Signal; use unit_parser::prelude::UnitConfig; use crate::{comm::MountUnitComm, rentry::SectionMount}; @@ -30,19 +33,36 @@ pub(super) struct MountConfig { // owned objects data: Rc>, + kill_context: Rc, + mount_parameters: RefCell, + mount_parameters_from_mountinfo: RefCell, } +#[derive(Clone)] pub(super) struct MountParameters { pub what: String, pub options: String, pub fstype: String, } +impl MountParameters { + fn empty() -> Self { + Self { + what: String::new(), + options: String::new(), + fstype: String::new(), + } + } +} + impl MountConfig { pub(super) fn new(commr: &Rc) -> Self { MountConfig { comm: Rc::clone(commr), data: Rc::new(RefCell::new(MountConfigData::default())), + kill_context: Rc::new(KillContext::default()), + mount_parameters: RefCell::new(MountParameters::empty()), + mount_parameters_from_mountinfo: RefCell::new(MountParameters::empty()), } } @@ -56,7 +76,16 @@ impl MountConfig { } }; *self.data.borrow_mut() = mount_config; + if let Err(e) = self.parse_kill_context() { + log::error!("Failed to parse KillContext for {}: {}", name, e); + } + self.set_mount_parameters(MountParameters { + what: self.mount_what(), + options: self.mount_options(), + fstype: self.mount_type(), + }) + // Todo: reli // if update { // self.db_update(); // } @@ -96,17 +125,58 @@ impl MountConfig { } pub(super) fn mount_parameters(&self) -> MountParameters { - MountParameters { - what: self.mount_what(), - options: self.mount_options(), - fstype: self.mount_type(), + (*self.mount_parameters.borrow()).clone() + } + + pub(super) fn set_mount_parameters(&self, mount_parameters: MountParameters) { + *self.mount_parameters.borrow_mut() = mount_parameters + } + + pub(super) fn mount_parameters_from_mountinfo(&self) -> MountParameters { + (*self.mount_parameters_from_mountinfo.borrow()).clone() + } + + pub(super) fn set_mount_parameters_from_mountinfo(&self, mount_parameters: MountParameters) { + *self.mount_parameters_from_mountinfo.borrow_mut() = mount_parameters + } + + /// update the mount parameters. return true if parameters are updated, return false if + /// parameters are not changed + pub(super) fn updated_mount_parameters_from_mountinfo( + &self, + what: &str, + options: &str, + fstype: &str, + ) -> bool { + let mut parameter_changed = false; + let mut mount_parameters = self.mount_parameters_from_mountinfo(); + if !mount_parameters.what.eq(what) { + mount_parameters.what = what.to_string(); + parameter_changed = true; + } + if !mount_parameters.options.eq(options) { + mount_parameters.options = options.to_string(); + parameter_changed = true; + } + if !mount_parameters.fstype.eq(fstype) { + mount_parameters.fstype = fstype.to_string(); + parameter_changed = true; } + self.set_mount_parameters_from_mountinfo(mount_parameters); + parameter_changed } - pub(super) fn update_mount_parameters(&self, what: &str, options: &str, fstype: &str) { - (*self.data.borrow_mut()).Mount.What = what.to_string(); - (*self.data.borrow_mut()).Mount.Options = options.to_string(); - (*self.data.borrow_mut()).Mount.Type = fstype.to_string(); + pub(super) fn kill_context(&self) -> Rc { + self.kill_context.clone() + } + + pub(super) fn parse_kill_context(&self) -> Result<()> { + self.kill_context + .set_kill_mode(self.config_data().borrow().Mount.KillMode); + + let signal = Signal::from_str(&self.config_data().borrow().Mount.KillSignal)?; + self.kill_context.set_kill_signal(signal); + Ok(()) } } diff --git a/core/coms/mount/src/manager.rs b/core/coms/mount/src/manager.rs index 5a0345bf..6ea063c8 100644 --- a/core/coms/mount/src/manager.rs +++ b/core/coms/mount/src/manager.rs @@ -404,12 +404,9 @@ impl MountMonitorData { pub fn dispatch_mountinfo(&self) -> Result<()> { let unit_type = Some(UnitType::UnitMount); - for unit in self.comm.um().units_get_all(unit_type).iter() { - self.comm.um().update_mount_state(unit, "dead"); - } self.load_mountinfo()?; for unit in self.comm.um().units_get_all(unit_type).iter() { - self.comm.um().update_mount_state(unit, "mounted"); + self.comm.um().update_mount_state_by_mountinfo(unit); } Ok(()) } diff --git a/core/coms/mount/src/mng.rs b/core/coms/mount/src/mng.rs index 1bbdabee..38d4ea4b 100644 --- a/core/coms/mount/src/mng.rs +++ b/core/coms/mount/src/mng.rs @@ -15,9 +15,10 @@ use basic::fs_util::{directory_is_empty, mkdir_p_label}; use basic::mount_util::filter_options; use basic::{MOUNT_BIN, UMOUNT_BIN}; use nix::sys::wait::WaitStatus; +use nix::unistd::Pid; use crate::config::{mount_is_bind, MountConfig}; -use crate::rentry::MountResult; +use crate::rentry::{MountProcFlags, MountResult}; use crate::spawn::MountSpawn; use super::comm::MountUnitComm; @@ -33,8 +34,17 @@ impl MountState { fn mount_state_to_unit_state(&self) -> UnitActiveState { match *self { MountState::Dead => UnitActiveState::InActive, + MountState::Mounting => UnitActiveState::Activating, + MountState::MountingDone => UnitActiveState::Activating, MountState::Mounted => UnitActiveState::Active, - _ => UnitActiveState::InActive, + MountState::Remounting + | MountState::RemountingSigKill + | MountState::RemountingSigterm => UnitActiveState::Reloading, + MountState::Unmounting + | MountState::UnmountingSigkill + | MountState::UnmountingSigterm => UnitActiveState::DeActivating, + MountState::Failed => UnitActiveState::Failed, + _ => UnitActiveState::Maintenance, } } } @@ -50,6 +60,8 @@ pub(super) struct MountMng { result: RefCell, reload_result: RefCell, find_in_mountinfo: RefCell, + proc_flags: RefCell, + pid: RefCell>, } impl ReStation for MountMng { @@ -84,6 +96,8 @@ impl MountMng { result: RefCell::new(MountResult::Success), reload_result: RefCell::new(MountResult::Success), find_in_mountinfo: RefCell::new(false), + proc_flags: RefCell::new(MountProcFlags::EMPTY), + pid: RefCell::new(None), } } @@ -136,28 +150,98 @@ impl MountMng { mount_command.append_many_argv(vec!["-o", &filtered_options]); } *self.control_command.borrow_mut() = Some(mount_command.clone()); - if let Err(e) = self.spawn.spawn_cmd(&mount_command) { - log::error!( - "Failed to mount {} to {}: {}", - &mount_config.Mount.What, - &mount_config.Mount.Where, + let control_pid = match self.spawn.spawn_cmd(&mount_command) { + Err(e) => { + log::error!( + "Failed to mount {} to {}: {}", + &mount_config.Mount.What, + &mount_config.Mount.Where, + e + ); + return; + } + Ok(v) => v, + }; + self.set_control_pid(control_pid); + + self.set_state(MountState::Mounting, true); + } + + pub(super) fn enter_signal(&self, state: MountState, res: MountResult) { + if self.result() == MountResult::Success { + self.set_result(res); + } + let unit = match self.comm.owner() { + None => { + log::error!( + "Failed to determine the owner unit if {}, ignoring", + self.comm.get_owner_id() + ); + return; + } + Some(v) => v, + }; + let kill_option = state.to_kill_option(); + let ret = unit.kill_context( + self.config.kill_context(), + None, + self.control_pid(), + kill_option, + false, + ); + if let Err(e) = ret { + log::warn!( + "Failed to kill process of {}: {}", + self.comm.get_owner_id(), e ); + self.enter_dead_or_mounted(MountResult::FailureResources); return; } - self.set_state(MountState::Mounting, true); + if ret.unwrap() { + // enable timer + self.set_state(state, true); + return; + } else if self.state() == MountState::RemountingSigterm { + self.enter_signal(MountState::RemountingSigKill, MountResult::Success); + } else if self.state() == MountState::RemountingSigKill { + self.enter_mounted(MountResult::Success, true); + } else if self.state() == MountState::UnmountingSigterm { + self.enter_signal(MountState::UnmountingSigkill, MountResult::Success); + } else { + self.enter_dead_or_mounted(MountResult::Success); + } } - pub(super) fn enter_signal(&self, _state: MountState, _res: MountResult) {} - - pub(super) fn enter_dead_or_mounted(&self, _res: MountResult) {} + pub(super) fn enter_dead_or_mounted(&self, res: MountResult) { + if self.find_in_mountinfo() { + self.enter_mounted(res, true); + } else { + self.enter_dead(res, true); + } + } - pub(super) fn enter_dead(&self, _res: MountResult, notify: bool) { - self.set_state(MountState::Dead, notify); + pub(super) fn enter_dead(&self, res: MountResult, notify: bool) { + if self.result() == MountResult::Success { + self.set_result(res); + } + log::info!("Mountpoint {} enter dead", self.comm.get_owner_id()); + if self.result() == MountResult::Success { + self.set_state(MountState::Dead, true); + } else { + self.set_state(MountState::Failed, true); + } } - pub(super) fn enter_mounted(&self, notify: bool) { + pub(super) fn enter_mounted(&self, res: MountResult, notify: bool) { + log::info!( + "(whorwe)enter_mounted: 1 | id: {}", + self.comm.get_owner_id() + ); + if self.result() == MountResult::Success { + self.set_result(res); + } self.set_state(MountState::Mounted, notify); } @@ -170,15 +254,58 @@ impl MountMng { let mount_where = self.config.mount_where(); umount_command.append_many_argv(vec![&mount_where, "-c"]); *self.control_command.borrow_mut() = Some(umount_command.clone()); - if let Err(e) = self.spawn.spawn_cmd(&umount_command) { - log::error!("Failed to umount {}: {}", mount_where, e); - return; - } + let control_pid = match self.spawn.spawn_cmd(&umount_command) { + Err(e) => { + log::error!("Failed to umount {}: {}", mount_where, e); + return; + } + Ok(v) => v, + }; + self.set_control_pid(control_pid); self.set_state(MountState::Unmounting, true); } - #[allow(unused)] - pub(super) fn enter_remounting(&self) {} + pub(super) fn enter_remounting(&self) { + self.set_result(MountResult::Success); + let mount_parameters = self.config.mount_parameters(); + let options = if mount_parameters.options.is_empty() { + "remount".to_string() + } else { + "remount".to_string() + &mount_parameters.options + }; + let mut remount_command = ExecCommand::empty(); + if let Err(e) = remount_command.set_path(MOUNT_BIN) { + log::error!("Failed to set remount command: {}", e); + } + remount_command.append_many_argv(vec![ + &self.config.mount_what(), + &self.config.mount_where(), + "-o", + &options, + ]); + let control_pid = match self.spawn.spawn_cmd(&remount_command) { + Err(e) => { + log::error!( + "Failed to remount {} to {}: {}", + self.config.mount_what(), + self.config.mount_where(), + e + ); + self.set_reload_result(MountResult::FailureResources); + self.enter_dead_or_mounted(MountResult::Success); + return; + } + Ok(v) => v, + }; + self.set_control_pid(control_pid); + self.set_state(MountState::Remounting, true); + } + + pub(super) fn cycle_clear(&self) { + self.set_result(MountResult::Success); + self.set_reload_result(MountResult::Success); + // Todo: exec_command reset + } #[allow(unused)] pub(super) fn dispatch_timer(&self) {} @@ -207,7 +334,7 @@ impl MountMng { if [MountState::Mounting, MountState::MountingDone].contains(&self.state()) { return Ok(()); } - + self.cycle_clear(); self.enter_mounting(); Ok(()) } @@ -248,6 +375,35 @@ impl MountMng { Ok(0) } + pub fn update_mount_state_by_mountinfo(&self) { + // Todo: device state update + if !self.is_mounted() { + self.set_find_in_mountinfo(false); + self.config + .updated_mount_parameters_from_mountinfo("", "", ""); + match self.state() { + MountState::Mounted => self.enter_dead(MountResult::Success, true), + MountState::MountingDone => self.set_state(MountState::Mounting, true), + _ => {} + } + } else if self + .proc_flags + .borrow() + .intersects(MountProcFlags::JUST_MOUNTED | MountProcFlags::JUST_CHANGED) + { + match self.state() { + MountState::Dead | MountState::Failed => { + self.cycle_clear(); + self.enter_mounted(MountResult::Success, true) + } + MountState::Mounting => self.set_state(MountState::MountingDone, true), + // Trigger a notify + _ => self.set_state(self.state(), true), + } + } + self.set_proc_flags(MountProcFlags::EMPTY); + } + pub fn get_state(&self) -> String { let state = *self.state.borrow(); state.to_string() @@ -289,7 +445,7 @@ impl MountMng { self.state.replace(new_state); } - fn state(&self) -> MountState { + pub fn state(&self) -> MountState { *self.state.borrow() } @@ -319,15 +475,42 @@ impl MountMng { pub fn set_find_in_mountinfo(&self, find: bool) { *self.find_in_mountinfo.borrow_mut() = find } + + pub fn set_proc_flags(&self, proc_flags: MountProcFlags) { + *self.proc_flags.borrow_mut() = proc_flags + } + + pub fn append_proc_flags(&self, new_proc_flags: MountProcFlags) { + let cur = *self.proc_flags.borrow(); + *self.proc_flags.borrow_mut() = cur | new_proc_flags + } + + pub fn is_mounted(&self) -> bool { + self.proc_flags + .borrow() + .contains(MountProcFlags::IS_MOUNTED) + } + + pub fn set_control_pid(&self, control_pid: Pid) { + *self.pid.borrow_mut() = Some(control_pid); + } + + pub fn control_pid(&self) -> Option { + self.pid.borrow().clone() + } } impl MountMng { pub(super) fn sigchld_event(&self, wait_status: WaitStatus) { + if self.control_pid() != wait_status.pid() { + return; + } self.do_sigchld_event(wait_status); self.db_update(); } fn do_sigchld_event(&self, wait_status: WaitStatus) { + self.set_control_pid(Pid::from_raw(0)); log::debug!("Got a mount process sigchld, status: {:?}", wait_status); let mut f = self.sigchld_result(wait_status); let state = self.state(); @@ -362,7 +545,7 @@ impl MountMng { // we have seen this mountpoint in /p/s/mountinfo if state == MountState::MountingDone { - self.enter_mounted(true); + self.enter_mounted(MountResult::Success, true); return; } @@ -380,7 +563,7 @@ impl MountMng { if state == MountState::Unmounting { // umount process has exited, but we can still see the mountpoint in /p/s/mountinfo if f == MountResult::Success && self.find_in_mountinfo() { - self.enter_mounted(true); + self.enter_mounted(MountResult::Success, true); } else { self.enter_dead_or_mounted(f); } diff --git a/core/coms/mount/src/rentry.rs b/core/coms/mount/src/rentry.rs index ef19514f..d6142ef8 100644 --- a/core/coms/mount/src/rentry.rs +++ b/core/coms/mount/src/rentry.rs @@ -10,9 +10,11 @@ // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. +use bitflags::bitflags; use core::{ exec::{PreserveMode, Rlimit, RuntimeDirectory, StateDirectory, WorkingDirectory}, rel::{ReDb, ReDbRwTxn, ReDbTable, ReliSwitch, Reliability}, + unit::{KillMode, KillOperation}, }; use macros::{EnumDisplay, UnitSection}; use serde::{Deserialize, Serialize}; @@ -39,6 +41,19 @@ pub(super) enum MountState { // Cleaning currently not used } +impl MountState { + pub fn to_kill_option(self) -> KillOperation { + match self { + MountState::RemountingSigterm => KillOperation::KillRestart, + MountState::UnmountingSigterm => KillOperation::KillTerminate, + MountState::RemountingSigKill | MountState::UnmountingSigkill => { + KillOperation::KillKill + } + _ => KillOperation::KillInvalid, + } + } +} + #[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize)] pub(super) enum MountResult { Success, @@ -51,6 +66,20 @@ pub(super) enum MountResult { FailureProtocol, } +bitflags! { + /// Flags set when process /p/s/mountinfo + pub struct MountProcFlags: u16 { + /// Initial state: empty + const EMPTY = 0; + /// The mountpoint is mounted + const IS_MOUNTED = 1 << 0; + /// The mountpoint is just mounted + const JUST_MOUNTED = 1 << 1; + /// Some mount parameters are changed + const JUST_CHANGED = 1 << 2; + } +} + #[derive(Clone, Debug, Serialize, Deserialize)] struct MountReMng { state: MountState, @@ -204,4 +233,10 @@ pub struct SectionMount { #[entry(append)] pub EnvironmentFile: Vec, pub SELinuxContext: Option, + + // Kill + #[entry(default = KillMode::ControlGroup)] + pub KillMode: KillMode, + #[entry(default = String::from("SIGTERM"))] + pub KillSignal: String, } diff --git a/core/coms/mount/src/unit.rs b/core/coms/mount/src/unit.rs index 17768c6d..db05aa1e 100644 --- a/core/coms/mount/src/unit.rs +++ b/core/coms/mount/src/unit.rs @@ -14,7 +14,7 @@ //! UnitObj,UnitMngUtil, UnitSubClass trait use crate::config::MountConfig; -use crate::rentry::MountResult; +use crate::rentry::{MountProcFlags, MountResult, MountState}; use super::comm::MountUnitComm; use super::mng::MountMng; @@ -178,14 +178,12 @@ impl SubUnit for MountUnit { } self.mng.start_action()?; - self.mng.enter_mounted(true); Ok(()) } fn stop(&self, _force: bool) -> Result<()> { self.mng.stop_action()?; - self.mng.enter_dead(MountResult::Success, true); Ok(()) } @@ -203,29 +201,36 @@ impl SubUnit for MountUnit { if self.config.mount_where().is_empty() { self.config.set_mount_where(mount_where); } - self.config.update_mount_parameters(what, options, fstype); + + self.mng.append_proc_flags(MountProcFlags::IS_MOUNTED); + if self + .config + .updated_mount_parameters_from_mountinfo(what, options, fstype) + { + self.mng.append_proc_flags(MountProcFlags::JUST_CHANGED); + } + if !self.mng.find_in_mountinfo() && self.mng.state() == MountState::Mounting { + self.mng.append_proc_flags(MountProcFlags::JUST_MOUNTED); + } self.mng.set_find_in_mountinfo(true); + // Todo: update dependencies. } fn setup_new_mount(&self, what: &str, mount_where: &str, options: &str, fstype: &str) { self.config.set_mount_where(mount_where); - self.config.update_mount_parameters(what, options, fstype); + self.config + .updated_mount_parameters_from_mountinfo(what, options, fstype); + // Todo: add dependencies. self.mng.set_find_in_mountinfo(true); + self.mng.set_proc_flags( + MountProcFlags::IS_MOUNTED + | MountProcFlags::JUST_MOUNTED + | MountProcFlags::JUST_CHANGED, + ); } - fn update_mount_state(&self, state: &str) { - match state { - "dead" => { - self.mng.set_find_in_mountinfo(false); - self.mng.enter_dead(MountResult::Success, true); - } - "mounted" => { - if self.mng.find_in_mountinfo() { - self.mng.enter_mounted(true); - } - } - _ => {} - } + fn update_mount_state_by_mountinfo(&self) { + self.mng.update_mount_state_by_mountinfo() } } diff --git a/core/coms/service/src/rentry.rs b/core/coms/service/src/rentry.rs index 798a2724..ad86318b 100644 --- a/core/coms/service/src/rentry.rs +++ b/core/coms/service/src/rentry.rs @@ -270,16 +270,12 @@ pub struct SectionService { pub NotifyAccess: Option, #[entry(default = false)] pub NonBlocking: bool, - #[entry(default = KillMode::ControlGroup)] - pub KillMode: KillMode, #[entry(default = ServiceRestart::No)] pub Restart: ServiceRestart, #[entry(default = ExitStatusSet::default())] pub RestartPreventExitStatus: ExitStatusSet, #[entry(default = 1)] pub RestartSec: u64, - #[entry(default = String::from("SIGTERM"))] - pub KillSignal: String, #[entry(default = 10000000, parser = parse_timeout)] pub TimeoutSec: u64, #[entry(default = 10000000, parser = parse_timeout)] @@ -312,6 +308,12 @@ pub struct SectionService { #[entry(append)] pub EnvironmentFile: Vec, pub SELinuxContext: Option, + + // Kill + #[entry(default = KillMode::ControlGroup)] + pub KillMode: KillMode, + #[entry(default = String::from("SIGTERM"))] + pub KillSignal: String, } impl SectionService { diff --git a/core/coms/socket/src/rentry.rs b/core/coms/socket/src/rentry.rs index a54d1d63..1886f970 100644 --- a/core/coms/socket/src/rentry.rs +++ b/core/coms/socket/src/rentry.rs @@ -104,6 +104,8 @@ pub(super) struct SectionSocket { pub SocketUser: String, #[entry(default = String::new())] pub SocketGroup: String, + + // Kill #[entry(default = KillMode::ControlGroup)] pub KillMode: KillMode, #[entry(default = String::from("SIGTERM"))] diff --git a/core/libcore/src/unit/base.rs b/core/libcore/src/unit/base.rs index 3f0df840..52224dcc 100644 --- a/core/libcore/src/unit/base.rs +++ b/core/libcore/src/unit/base.rs @@ -177,7 +177,7 @@ pub trait SubUnit: ReStation + UnitMngUtil { fn setup_new_mount(&self, _what: &str, _mount_where: &str, _options: &str, _fstype: &str) {} /// - fn update_mount_state(&self, _state: &str) {} + fn update_mount_state_by_mountinfo(&self) {} } /// the macro for create a sub unit instance with dyn ref of UmIf, diff --git a/core/libcore/src/unit/umif.rs b/core/libcore/src/unit/umif.rs index 62df8215..205055d4 100644 --- a/core/libcore/src/unit/umif.rs +++ b/core/libcore/src/unit/umif.rs @@ -230,7 +230,7 @@ pub trait UmIf { } /// update mount state - fn update_mount_state(&self, _unit_name: &str, _state: &str) {} + fn update_mount_state_by_mountinfo(&self, _unit_name: &str) {} } /// the trait used for attach UnitManager to sub unit diff --git a/core/sysmaster/src/unit/entry/uentry.rs b/core/sysmaster/src/unit/entry/uentry.rs index 25d2adf2..f6ba2e0a 100644 --- a/core/sysmaster/src/unit/entry/uentry.rs +++ b/core/sysmaster/src/unit/entry/uentry.rs @@ -759,7 +759,7 @@ impl Unit { self.load.load_state() } - pub(super) fn set_load_state(&self, state: UnitLoadState) { + pub fn set_load_state(&self, state: UnitLoadState) { self.load.set_load_state(state) } @@ -808,8 +808,8 @@ impl Unit { self.sub.setup_new_mount(what, mount_where, options, fstype); } - pub(crate) fn update_mount_state(&self, state: &str) { - self.sub.update_mount_state(state); + pub(crate) fn update_mount_state_by_mountinfo(&self) { + self.sub.update_mount_state_by_mountinfo(); } pub(crate) fn notify_message( diff --git a/core/sysmaster/src/unit/manager.rs b/core/sysmaster/src/unit/manager.rs index 18cfb231..4dc79b56 100644 --- a/core/sysmaster/src/unit/manager.rs +++ b/core/sysmaster/src/unit/manager.rs @@ -674,7 +674,16 @@ impl UmIf for UnitManager { } Some(v) => v, }; + log::info!( + "(whorwe)setup_existing_mount: 1 | id: {}, {}-{}-{}-{}", + mount.id(), + what, + mount_where, + options, + fstype + ); mount.setup_existing_mount(what, mount_where, options, fstype); + mount.set_load_state(UnitLoadState::Loaded); } /// setup new mount @@ -701,7 +710,7 @@ impl UmIf for UnitManager { } /// update mount state - fn update_mount_state(&self, unit_name: &str, state: &str) { + fn update_mount_state_by_mountinfo(&self, unit_name: &str) { let mount = match self.units_get(unit_name) { None => { log::error!("Failed to update the mount state of {}", unit_name); @@ -709,7 +718,7 @@ impl UmIf for UnitManager { } Some(v) => v, }; - mount.update_mount_state(state); + mount.update_mount_state_by_mountinfo(); } } -- Gitee From e479e198c8ad6f655fbf2145d0871b4764ac0e9c Mon Sep 17 00:00:00 2001 From: licunlong Date: Thu, 7 Dec 2023 14:59:49 +0800 Subject: [PATCH 2/5] feature: watch and unwatch pid --- core/coms/mount/src/mng.rs | 41 +++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/core/coms/mount/src/mng.rs b/core/coms/mount/src/mng.rs index 38d4ea4b..71468490 100644 --- a/core/coms/mount/src/mng.rs +++ b/core/coms/mount/src/mng.rs @@ -150,6 +150,7 @@ impl MountMng { mount_command.append_many_argv(vec!["-o", &filtered_options]); } *self.control_command.borrow_mut() = Some(mount_command.clone()); + self.unwatch_control_pid(); let control_pid = match self.spawn.spawn_cmd(&mount_command) { Err(e) => { log::error!( @@ -162,8 +163,8 @@ impl MountMng { } Ok(v) => v, }; - self.set_control_pid(control_pid); - + self.set_control_pid(Some(control_pid)); + self.watch_control_pid(); self.set_state(MountState::Mounting, true); } @@ -246,7 +247,7 @@ impl MountMng { } pub(super) fn enter_unmounting(&self) { - // retry_umount + // Todo: retry_umount let mut umount_command = ExecCommand::empty(); if let Err(e) = umount_command.set_path(UMOUNT_BIN) { log::error!("Failed to set umount command: {}", e); @@ -254,6 +255,7 @@ impl MountMng { let mount_where = self.config.mount_where(); umount_command.append_many_argv(vec![&mount_where, "-c"]); *self.control_command.borrow_mut() = Some(umount_command.clone()); + self.unwatch_control_pid(); let control_pid = match self.spawn.spawn_cmd(&umount_command) { Err(e) => { log::error!("Failed to umount {}: {}", mount_where, e); @@ -261,7 +263,8 @@ impl MountMng { } Ok(v) => v, }; - self.set_control_pid(control_pid); + self.set_control_pid(Some(control_pid)); + self.watch_control_pid(); self.set_state(MountState::Unmounting, true); } @@ -283,6 +286,8 @@ impl MountMng { "-o", &options, ]); + *self.control_command.borrow_mut() = Some(remount_command.clone()); + self.unwatch_control_pid(); let control_pid = match self.spawn.spawn_cmd(&remount_command) { Err(e) => { log::error!( @@ -297,14 +302,15 @@ impl MountMng { } Ok(v) => v, }; - self.set_control_pid(control_pid); + self.set_control_pid(Some(control_pid)); + self.watch_control_pid(); self.set_state(MountState::Remounting, true); } pub(super) fn cycle_clear(&self) { self.set_result(MountResult::Success); self.set_reload_result(MountResult::Success); - // Todo: exec_command reset + *self.control_command.borrow_mut() = None; } #[allow(unused)] @@ -491,13 +497,30 @@ impl MountMng { .contains(MountProcFlags::IS_MOUNTED) } - pub fn set_control_pid(&self, control_pid: Pid) { - *self.pid.borrow_mut() = Some(control_pid); + pub fn set_control_pid(&self, control_pid: Option) { + *self.pid.borrow_mut() = control_pid; } pub fn control_pid(&self) -> Option { self.pid.borrow().clone() } + + pub fn watch_control_pid(&self) { + if let Some(pid) = self.control_pid() { + if let Some(u) = self.comm.owner() { + self.comm.um().child_watch_pid(&u.id(), pid); + } + } + } + + pub fn unwatch_control_pid(&self) { + if let Some(pid) = self.control_pid() { + if let Some(u) = self.comm.owner() { + self.comm.um().child_unwatch_pid(&u.id(), pid) + } + self.set_control_pid(None); + } + } } impl MountMng { @@ -510,7 +533,7 @@ impl MountMng { } fn do_sigchld_event(&self, wait_status: WaitStatus) { - self.set_control_pid(Pid::from_raw(0)); + self.set_control_pid(None); log::debug!("Got a mount process sigchld, status: {:?}", wait_status); let mut f = self.sigchld_result(wait_status); let state = self.state(); -- Gitee From d9688da3eb36ef1fa8b6c933fa6c5fbf4ef2dc31 Mon Sep 17 00:00:00 2001 From: licunlong Date: Thu, 7 Dec 2023 17:12:09 +0800 Subject: [PATCH 3/5] feature: enable timer --- core/coms/mount/src/mng.rs | 146 +++++++++++++++++++++++++++++++++-- core/coms/mount/src/spawn.rs | 15 +++- core/coms/mount/src/unit.rs | 4 +- 3 files changed, 158 insertions(+), 7 deletions(-) diff --git a/core/coms/mount/src/mng.rs b/core/coms/mount/src/mng.rs index 71468490..9b06e444 100644 --- a/core/coms/mount/src/mng.rs +++ b/core/coms/mount/src/mng.rs @@ -13,7 +13,10 @@ //! The core logic of the mount subclass use basic::fs_util::{directory_is_empty, mkdir_p_label}; use basic::mount_util::filter_options; +use basic::time_util::USEC_PER_SEC; use basic::{MOUNT_BIN, UMOUNT_BIN}; +use event::{EventState, Events}; +use event::{EventType, Source}; use nix::sys::wait::WaitStatus; use nix::unistd::Pid; @@ -27,7 +30,9 @@ use core::error::*; use core::exec::{ExecCommand, ExecContext}; use core::rel::ReStation; use core::unit::{UnitActiveState, UnitNotifyFlags}; +use std::os::unix::prelude::RawFd; use std::path::Path; +use std::rc::Weak; use std::{cell::RefCell, rc::Rc}; impl MountState { @@ -44,7 +49,6 @@ impl MountState { | MountState::UnmountingSigkill | MountState::UnmountingSigterm => UnitActiveState::DeActivating, MountState::Failed => UnitActiveState::Failed, - _ => UnitActiveState::Maintenance, } } } @@ -56,12 +60,14 @@ pub(super) struct MountMng { config: Rc, control_command: RefCell>, spawn: Rc, + timer: Rc, result: RefCell, reload_result: RefCell, find_in_mountinfo: RefCell, proc_flags: RefCell, pid: RefCell>, + timeout_usec: RefCell, } impl ReStation for MountMng { @@ -93,11 +99,13 @@ impl MountMng { config: Rc::clone(configr), control_command: RefCell::new(None), spawn: Rc::new(MountSpawn::new(commr, exec_ctx)), + timer: Rc::new(MountTimer::new(u64::MAX)), result: RefCell::new(MountResult::Success), reload_result: RefCell::new(MountResult::Success), find_in_mountinfo: RefCell::new(false), proc_flags: RefCell::new(MountProcFlags::EMPTY), pid: RefCell::new(None), + timeout_usec: RefCell::new(90 * USEC_PER_SEC), } } @@ -229,9 +237,9 @@ impl MountMng { } log::info!("Mountpoint {} enter dead", self.comm.get_owner_id()); if self.result() == MountResult::Success { - self.set_state(MountState::Dead, true); + self.set_state(MountState::Dead, notify); } else { - self.set_state(MountState::Failed, true); + self.set_state(MountState::Failed, notify); } } @@ -268,6 +276,7 @@ impl MountMng { self.set_state(MountState::Unmounting, true); } + #[allow(unused)] pub(super) fn enter_remounting(&self) { self.set_result(MountResult::Success); let mount_parameters = self.config.mount_parameters(); @@ -313,8 +322,74 @@ impl MountMng { *self.control_command.borrow_mut() = None; } - #[allow(unused)] - pub(super) fn dispatch_timer(&self) {} + pub(super) fn timeout_usec(&self) -> u64 { + *self.timeout_usec.borrow() + } + + pub(super) fn attach_spawn(&self, mng: &Rc) { + self.spawn.attach_mng(mng) + } + + pub(super) fn timer(&self) -> Rc { + self.timer.clone() + } + + pub(super) fn attach_timer(&self, mng: &Rc) { + self.timer.attach_mng(mng) + } + + pub(super) fn enable_timer(&self, usec: u64) -> Result { + let events = self.comm.um().events(); + if usec == u64::MAX { + events.del_source(self.timer())?; + return Ok(0); + } + log::debug!("Enable a timer: {}us", usec); + + let timer = self.timer(); + events.del_source(timer.clone())?; + + timer.set_time(usec); + events.add_source(timer.clone())?; + events.set_enabled(timer, EventState::OneShot)?; + + Ok(0) + } + + pub(super) fn dispatch_timer(&self) -> i32 { + log::info!("Dispatch timeout event for {}", self.comm.get_owner_id()); + match self.state() { + MountState::Mounting | MountState::MountingDone => { + self.enter_signal(MountState::UnmountingSigterm, MountResult::FailureTimeout); + } + MountState::Remounting => { + self.set_reload_result(MountResult::FailureTimeout); + self.enter_signal(MountState::RemountingSigterm, MountResult::Success); + } + MountState::RemountingSigterm => { + self.set_reload_result(MountResult::FailureTimeout); + // Todo: check if SendKill is configured to yes + self.enter_signal(MountState::RemountingSigKill, MountResult::Success); + } + MountState::RemountingSigKill => { + self.set_reload_result(MountResult::FailureTimeout); + self.enter_dead_or_mounted(MountResult::Success); + } + MountState::Unmounting => { + self.enter_signal(MountState::UnmountingSigterm, MountResult::FailureTimeout); + } + MountState::UnmountingSigterm => { + // Todo: check SendKill + self.enter_signal(MountState::UnmountingSigkill, MountResult::FailureTimeout); + } + MountState::UnmountingSigkill => { + self.enter_dead_or_mounted(MountResult::FailureTimeout); + } + // Dead, Mounted, Failed should be impossible here. + _ => return -1, + } + 0 + } pub(super) fn start_check(&self) -> Result { let ret = self.comm.owner().map_or(false, |u| u.test_start_limit()); @@ -619,6 +694,67 @@ impl MountMng { } } +pub(super) struct MountTimer { + time: RefCell, + mng: RefCell>, +} + +impl MountTimer { + pub fn new(usec: u64) -> Self { + MountTimer { + time: RefCell::new(usec), + mng: RefCell::new(Weak::new()), + } + } + + pub(super) fn attach_mng(&self, mng: &Rc) { + *self.mng.borrow_mut() = Rc::downgrade(mng) + } + + pub(super) fn set_time(&self, usec: u64) { + *self.time.borrow_mut() = usec + } + + pub(self) fn mng(&self) -> Rc { + self.mng.borrow().clone().upgrade().unwrap() + } + + fn do_dispatch(&self) -> i32 { + self.mng().dispatch_timer() + } +} + +impl Source for MountTimer { + fn fd(&self) -> RawFd { + 0 + } + + fn event_type(&self) -> EventType { + EventType::TimerMonotonic + } + + fn epoll_event(&self) -> u32 { + (libc::EPOLLIN) as u32 + } + + fn time_relative(&self) -> u64 { + *self.time.borrow() + } + + fn dispatch(&self, _: &Events) -> i32 { + self.do_dispatch() + } + + fn priority(&self) -> i8 { + 0 + } + + fn token(&self) -> u64 { + let data: u64 = unsafe { std::mem::transmute(self) }; + data + } +} + // #[cfg(test)] // mod tests { // use super::MountMng; diff --git a/core/coms/mount/src/spawn.rs b/core/coms/mount/src/spawn.rs index 5a536536..f8022857 100644 --- a/core/coms/mount/src/spawn.rs +++ b/core/coms/mount/src/spawn.rs @@ -13,14 +13,17 @@ use core::error::*; use core::exec::{ExecCommand, ExecContext, ExecParameters}; -use std::rc::Rc; +use std::cell::RefCell; +use std::rc::{Rc, Weak}; use nix::unistd::Pid; use crate::comm::MountUnitComm; +use crate::mng::MountMng; pub(crate) struct MountSpawn { comm: Rc, + mng: RefCell>, exec_ctx: Rc, } @@ -28,11 +31,21 @@ impl MountSpawn { pub(super) fn new(comm: &Rc, exec_ctx: &Rc) -> MountSpawn { MountSpawn { comm: comm.clone(), + mng: RefCell::new(Weak::new()), exec_ctx: exec_ctx.clone(), } } + pub(super) fn attach_mng(&self, mng: &Rc) { + *self.mng.borrow_mut() = Rc::downgrade(mng); + } + + pub(super) fn mng(&self) -> Rc { + self.mng.borrow().upgrade().unwrap().clone() + } + pub(super) fn spawn_cmd(&self, cmdline: &ExecCommand) -> Result { + let _ = self.mng().enable_timer(self.mng().timeout_usec()); let mut params = ExecParameters::new(); if let Some(unit) = self.comm.owner() { diff --git a/core/coms/mount/src/unit.rs b/core/coms/mount/src/unit.rs index db05aa1e..e8c952cc 100644 --- a/core/coms/mount/src/unit.rs +++ b/core/coms/mount/src/unit.rs @@ -14,7 +14,7 @@ //! UnitObj,UnitMngUtil, UnitSubClass trait use crate::config::MountConfig; -use crate::rentry::{MountProcFlags, MountResult, MountState}; +use crate::rentry::{MountProcFlags, MountState}; use super::comm::MountUnitComm; use super::mng::MountMng; @@ -64,6 +64,8 @@ impl MountUnit { let config = Rc::new(MountConfig::new(&comm)); let exec_ctx = Rc::new(ExecContext::new()); let mng = Rc::new(MountMng::new(&comm, &config, &exec_ctx)); + mng.attach_spawn(&mng); + mng.attach_timer(&mng); MountUnit { comm, mng, -- Gitee From ed2330bc1c4bcd76dc7b1b3ca58be380ee7e37ae Mon Sep 17 00:00:00 2001 From: licunlong Date: Thu, 7 Dec 2023 17:25:21 +0800 Subject: [PATCH 4/5] feature: enable reload and reset-failed --- core/coms/mount/src/mng.rs | 13 ++++++++----- core/coms/mount/src/unit.rs | 9 ++++++++- core/sysmaster/src/unit/manager.rs | 8 -------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/core/coms/mount/src/mng.rs b/core/coms/mount/src/mng.rs index 9b06e444..b0cd10d5 100644 --- a/core/coms/mount/src/mng.rs +++ b/core/coms/mount/src/mng.rs @@ -244,10 +244,6 @@ impl MountMng { } pub(super) fn enter_mounted(&self, res: MountResult, notify: bool) { - log::info!( - "(whorwe)enter_mounted: 1 | id: {}", - self.comm.get_owner_id() - ); if self.result() == MountResult::Success { self.set_result(res); } @@ -276,7 +272,6 @@ impl MountMng { self.set_state(MountState::Unmounting, true); } - #[allow(unused)] pub(super) fn enter_remounting(&self) { self.set_result(MountResult::Success); let mount_parameters = self.config.mount_parameters(); @@ -485,6 +480,14 @@ impl MountMng { self.set_proc_flags(MountProcFlags::EMPTY); } + pub fn reset_failed(&self) { + if self.state() == MountState::Failed { + self.set_state(MountState::Dead, true); + } + self.set_result(MountResult::Success); + self.set_reload_result(MountResult::Success); + } + pub fn get_state(&self) -> String { let state = *self.state.borrow(); state.to_string() diff --git a/core/coms/mount/src/unit.rs b/core/coms/mount/src/unit.rs index e8c952cc..96ca0942 100644 --- a/core/coms/mount/src/unit.rs +++ b/core/coms/mount/src/unit.rs @@ -189,6 +189,11 @@ impl SubUnit for MountUnit { Ok(()) } + fn reload(&self) -> Result<()> { + self.mng.enter_remounting(); + Ok(()) + } + fn kill(&self) {} fn release_resources(&self) {} @@ -197,7 +202,9 @@ impl SubUnit for MountUnit { self.mng.sigchld_event(wait_status); } - fn reset_failed(&self) {} + fn reset_failed(&self) { + self.mng.reset_failed() + } fn setup_existing_mount(&self, what: &str, mount_where: &str, options: &str, fstype: &str) { if self.config.mount_where().is_empty() { diff --git a/core/sysmaster/src/unit/manager.rs b/core/sysmaster/src/unit/manager.rs index 4dc79b56..3941d46f 100644 --- a/core/sysmaster/src/unit/manager.rs +++ b/core/sysmaster/src/unit/manager.rs @@ -674,14 +674,6 @@ impl UmIf for UnitManager { } Some(v) => v, }; - log::info!( - "(whorwe)setup_existing_mount: 1 | id: {}, {}-{}-{}-{}", - mount.id(), - what, - mount_where, - options, - fstype - ); mount.setup_existing_mount(what, mount_where, options, fstype); mount.set_load_state(UnitLoadState::Loaded); } -- Gitee From 3825abdbbdb349e082c7ed07dd94229f2f2fcb6a Mon Sep 17 00:00:00 2001 From: licunlong Date: Mon, 11 Dec 2023 11:40:25 +0800 Subject: [PATCH 5/5] cleancode: fix cargo clippy --- core/coms/mount/src/mng.rs | 3 +-- core/coms/mount/src/spawn.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/coms/mount/src/mng.rs b/core/coms/mount/src/mng.rs index b0cd10d5..5d9842b1 100644 --- a/core/coms/mount/src/mng.rs +++ b/core/coms/mount/src/mng.rs @@ -211,7 +211,6 @@ impl MountMng { if ret.unwrap() { // enable timer self.set_state(state, true); - return; } else if self.state() == MountState::RemountingSigterm { self.enter_signal(MountState::RemountingSigKill, MountResult::Success); } else if self.state() == MountState::RemountingSigKill { @@ -580,7 +579,7 @@ impl MountMng { } pub fn control_pid(&self) -> Option { - self.pid.borrow().clone() + *self.pid.borrow() } pub fn watch_control_pid(&self) { diff --git a/core/coms/mount/src/spawn.rs b/core/coms/mount/src/spawn.rs index f8022857..4ef7b022 100644 --- a/core/coms/mount/src/spawn.rs +++ b/core/coms/mount/src/spawn.rs @@ -41,7 +41,7 @@ impl MountSpawn { } pub(super) fn mng(&self) -> Rc { - self.mng.borrow().upgrade().unwrap().clone() + self.mng.borrow().upgrade().unwrap() } pub(super) fn spawn_cmd(&self, cmdline: &ExecCommand) -> Result { -- Gitee