diff --git a/Cargo.lock b/Cargo.lock index 60c6b30e773b21b4ef8c15e5a6963d962aeda619..73ea1a301ad92922d8d59eb051641bf1606b0979 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 80f336a9c849f2f73e5cda7d763743a8d14c64b4..7128d82339e3ca762f65e72d2b6cf49de9441083 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 1bad5dde07d6e8a6c15583fd3610c5eac06418f2..074deaffed60261c7a3cd82312fb98470b9534da 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 5a0345bfbe05801e2adcfb3e89167dbd6602675b..6ea063c80d6432e4f00b0a256632b891839cd437 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 1bbdabeecbdeebbd5603ee7002cbe2a2b53b8fa3..5d9842b13cb924c28b4c6ac10ca8b65bc2a2f5ea 100644 --- a/core/coms/mount/src/mng.rs +++ b/core/coms/mount/src/mng.rs @@ -13,11 +13,15 @@ //! 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; use crate::config::{mount_is_bind, MountConfig}; -use crate::rentry::MountResult; +use crate::rentry::{MountProcFlags, MountResult}; use crate::spawn::MountSpawn; use super::comm::MountUnitComm; @@ -26,15 +30,25 @@ 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 { 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, } } } @@ -46,10 +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 { @@ -81,9 +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), } } @@ -136,33 +158,99 @@ 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, + self.unwatch_control_pid(); + 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(Some(control_pid)); + self.watch_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); + } 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, notify); + } else { + self.set_state(MountState::Failed, notify); + } } - pub(super) fn enter_mounted(&self, notify: bool) { + pub(super) fn enter_mounted(&self, res: MountResult, notify: bool) { + if self.result() == MountResult::Success { + self.set_result(res); + } self.set_state(MountState::Mounted, notify); } 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); @@ -170,18 +258,132 @@ 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; - } + self.unwatch_control_pid(); + 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(Some(control_pid)); + self.watch_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, + ]); + *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!( + "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(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); + *self.control_command.borrow_mut() = None; + } + + 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) + } - #[allow(unused)] - pub(super) fn dispatch_timer(&self) {} + 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()); @@ -207,7 +409,7 @@ impl MountMng { if [MountState::Mounting, MountState::MountingDone].contains(&self.state()) { return Ok(()); } - + self.cycle_clear(); self.enter_mounting(); Ok(()) } @@ -248,6 +450,43 @@ 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 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() @@ -289,7 +528,7 @@ impl MountMng { self.state.replace(new_state); } - fn state(&self) -> MountState { + pub fn state(&self) -> MountState { *self.state.borrow() } @@ -319,15 +558,59 @@ 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: Option) { + *self.pid.borrow_mut() = control_pid; + } + + pub fn control_pid(&self) -> Option { + *self.pid.borrow() + } + + 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 { 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(None); log::debug!("Got a mount process sigchld, status: {:?}", wait_status); let mut f = self.sigchld_result(wait_status); let state = self.state(); @@ -362,7 +645,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 +663,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); } @@ -413,6 +696,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/rentry.rs b/core/coms/mount/src/rentry.rs index ef19514fe7429e82f39ce32d6cfb2d6502e8ceee..d6142ef8f2c1317284c54d8849646a8517d2c856 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/spawn.rs b/core/coms/mount/src/spawn.rs index 5a536536e2cdcde8f9b14e9f765a462db868df95..4ef7b022ff357e7a96d449ee7721bf14195f84f5 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() + } + 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 17768c6d98385aa1ffdddc92825545ca33de430b..96ca094263ddfb89b7a79424f8ec7c49f9efe9aa 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, 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, @@ -178,14 +180,17 @@ 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(()) + } + + fn reload(&self) -> Result<()> { + self.mng.enter_remounting(); Ok(()) } @@ -197,35 +202,44 @@ 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() { 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 798a2724156f0a2cc2ca56cb309e406399556de6..ad86318b382e581b44ec97192dba12fa151a5999 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 a54d1d63098a3505a754837ebda9135d8a817ac0..1886f97028819123e596a02e08041235b54cba1d 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 3f0df840d9e29ea9d912ac0ef05d3341507cc306..52224dccfe914a100906d04e7d82d348c7f2a464 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 62df8215ddbfba1c02c1ca3af373df87d24e1693..205055d45b0ccac0a94f744600cb99ba32a02caa 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 25d2adf2473c4bf70132d3838e2ba46df9191e5d..f6ba2e0a64c980986f91df162a2d0d85a643a82e 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 18cfb231be9f1635ac8a857f0c04325640b35893..3941d46f4d8cf6682192edf884d0226c50a8e03e 100644 --- a/core/sysmaster/src/unit/manager.rs +++ b/core/sysmaster/src/unit/manager.rs @@ -675,6 +675,7 @@ impl UmIf for UnitManager { Some(v) => v, }; mount.setup_existing_mount(what, mount_where, options, fstype); + mount.set_load_state(UnitLoadState::Loaded); } /// setup new mount @@ -701,7 +702,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 +710,7 @@ impl UmIf for UnitManager { } Some(v) => v, }; - mount.update_mount_state(state); + mount.update_mount_state_by_mountinfo(); } }