Move the executable `PathOrInode` to `ProcessVm`
This commit is contained in:
parent
423053f2e6
commit
449939a32b
|
|
@ -26,7 +26,14 @@ impl CommFileOps {
|
|||
|
||||
impl FileOps for CommFileOps {
|
||||
fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result<usize> {
|
||||
let exe_path = self.0.executable_file().display_name();
|
||||
let vmar_guard = self.0.lock_vmar();
|
||||
let Some(vmar) = vmar_guard.as_ref() else {
|
||||
// According to Linux behavior, return an empty string
|
||||
// if the process is a zombie process.
|
||||
return Ok(0);
|
||||
};
|
||||
|
||||
let exe_path = vmar.process_vm().executable_file().display_name();
|
||||
let last_component = exe_path.rsplit('/').next().unwrap_or(&exe_path);
|
||||
let mut comm = last_component.as_bytes().to_vec();
|
||||
comm.truncate(TASK_COMM_LEN - 1);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,12 @@ impl ExeSymOps {
|
|||
|
||||
impl SymOps for ExeSymOps {
|
||||
fn read_link(&self) -> Result<SymbolicLink> {
|
||||
let res = match self.0.executable_file() {
|
||||
let vmar_guard = self.0.lock_vmar();
|
||||
let Some(vmar) = vmar_guard.as_ref() else {
|
||||
return_errno_with_message!(Errno::ENOENT, "the process has exited");
|
||||
};
|
||||
|
||||
let res = match vmar.process_vm().executable_file().clone() {
|
||||
PathOrInode::Path(path) => SymbolicLink::Path(path),
|
||||
PathOrInode::Inode(inode) => SymbolicLink::Inode(inode),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use crate::{
|
|||
fs::{
|
||||
cgroupfs::CgroupMembership,
|
||||
file_table::{FdFlags, FileTable},
|
||||
fs_resolver::PathOrInode,
|
||||
thread_info::ThreadFsInfo,
|
||||
},
|
||||
prelude::*,
|
||||
|
|
@ -489,10 +488,10 @@ fn clone_child_process(
|
|||
let child_tid = allocate_posix_tid();
|
||||
|
||||
let child = {
|
||||
let child_elf_file = process.executable_file();
|
||||
let mut child_thread_builder = {
|
||||
let child_thread_name =
|
||||
ThreadName::new_from_executable_path(&child_elf_file.display_name());
|
||||
let child_thread_name = ThreadName::new_from_executable_path(
|
||||
&child_vmar.process_vm().executable_file().display_name(),
|
||||
);
|
||||
|
||||
let credentials = {
|
||||
let credentials = ctx.posix_thread.credentials();
|
||||
|
|
@ -517,7 +516,6 @@ fn clone_child_process(
|
|||
|
||||
create_child_process(
|
||||
child_tid,
|
||||
child_elf_file,
|
||||
child_vmar,
|
||||
child_resource_limits,
|
||||
child_nice,
|
||||
|
|
@ -714,7 +712,6 @@ fn clone_ns_proxy(
|
|||
#[expect(clippy::too_many_arguments)]
|
||||
fn create_child_process(
|
||||
pid: Pid,
|
||||
child_elf_file: PathOrInode,
|
||||
vmar: Arc<Vmar>,
|
||||
resource_limits: ResourceLimits,
|
||||
nice: Nice,
|
||||
|
|
@ -725,7 +722,6 @@ fn create_child_process(
|
|||
) -> Arc<Process> {
|
||||
let child_proc = Process::new(
|
||||
pid,
|
||||
child_elf_file,
|
||||
vmar,
|
||||
resource_limits,
|
||||
nice,
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ fn do_execve_no_return(
|
|||
let elf_load_info = {
|
||||
let mut vmar = ctx.process.lock_vmar();
|
||||
// Reset the virtual memory state.
|
||||
unshare_and_renew_vmar(ctx, &mut vmar);
|
||||
unshare_and_renew_vmar(ctx, &mut vmar, elf_file.clone());
|
||||
// Load the binary into the process's address space
|
||||
program_to_load.load_to_vmar(vmar.unwrap(), fs_resolver)?
|
||||
};
|
||||
|
|
@ -166,7 +166,6 @@ fn do_execve_no_return(
|
|||
// Update the process's executable path and set the thread name
|
||||
let executable_path = elf_file.display_name();
|
||||
*posix_thread.thread_name().lock() = ThreadName::new_from_executable_path(&executable_path);
|
||||
process.set_executable_file(elf_file);
|
||||
|
||||
// Unshare and reset signal dispositions to their default actions.
|
||||
unshare_and_reset_sigdispositions(process);
|
||||
|
|
|
|||
|
|
@ -47,14 +47,6 @@ fn create_init_process(
|
|||
argv: Vec<CString>,
|
||||
envp: Vec<CString>,
|
||||
) -> Result<Arc<Process>> {
|
||||
let pid = allocate_posix_tid();
|
||||
let process_vm = new_vmar_and_map();
|
||||
let resource_limits = ResourceLimits::default();
|
||||
let nice = Nice::default();
|
||||
let oom_score_adj = 0;
|
||||
let sig_dispositions = Arc::new(Mutex::new(SigDispositions::default()));
|
||||
let user_ns = UserNamespace::get_init_singleton().clone();
|
||||
|
||||
let fs = {
|
||||
let fs_resolver = MountNamespace::get_init_singleton().new_fs_resolver();
|
||||
ThreadFsInfo::new(fs_resolver)
|
||||
|
|
@ -62,9 +54,16 @@ fn create_init_process(
|
|||
let fs_path = FsPath::try_from(executable_path)?;
|
||||
let elf_path = fs.resolver().read().lookup(&fs_path)?;
|
||||
|
||||
let pid = allocate_posix_tid();
|
||||
let process_vm = new_vmar_and_map(PathOrInode::Path(elf_path.clone()));
|
||||
let resource_limits = ResourceLimits::default();
|
||||
let nice = Nice::default();
|
||||
let oom_score_adj = 0;
|
||||
let sig_dispositions = Arc::new(Mutex::new(SigDispositions::default()));
|
||||
let user_ns = UserNamespace::get_init_singleton().clone();
|
||||
|
||||
let init_proc = Process::new(
|
||||
pid,
|
||||
PathOrInode::Path(elf_path.clone()),
|
||||
process_vm,
|
||||
resource_limits,
|
||||
nice,
|
||||
|
|
@ -114,11 +113,12 @@ fn create_init_task(
|
|||
let vmar = process.lock_vmar();
|
||||
program_to_load.load_to_vmar(vmar.unwrap(), &fs_resolver)?
|
||||
};
|
||||
|
||||
let mut user_ctx = UserContext::default();
|
||||
user_ctx.set_instruction_pointer(elf_load_info.entry_point as _);
|
||||
user_ctx.set_stack_pointer(elf_load_info.user_stack_top as _);
|
||||
|
||||
let thread_name = ThreadName::new_from_executable_path(&elf_path.abs_path());
|
||||
|
||||
let thread_builder = PosixThreadBuilder::new(tid, thread_name, Box::new(user_ctx), credentials)
|
||||
.process(Arc::downgrade(process))
|
||||
.fs(Arc::new(fs))
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
fs::cgroupfs::CgroupNode,
|
||||
fs::fs_resolver::PathOrInode,
|
||||
prelude::*,
|
||||
process::{
|
||||
signal::{sig_queues::SigQueues, Pollee},
|
||||
|
|
@ -87,8 +86,6 @@ pub struct Process {
|
|||
pub(super) pidfile_pollee: Pollee,
|
||||
|
||||
// Mutable Part
|
||||
/// The executable `PathOrInode`.
|
||||
executable_file: RwLock<PathOrInode>,
|
||||
/// The threads
|
||||
tasks: Mutex<TaskSet>,
|
||||
/// Process status
|
||||
|
|
@ -215,10 +212,8 @@ impl Process {
|
|||
Some(Task::current()?.as_posix_thread()?.process())
|
||||
}
|
||||
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub(super) fn new(
|
||||
pid: Pid,
|
||||
executable_file: PathOrInode,
|
||||
vmar: Arc<Vmar>,
|
||||
|
||||
resource_limits: ResourceLimits,
|
||||
|
|
@ -236,7 +231,6 @@ impl Process {
|
|||
Arc::new_cyclic(|process_ref: &Weak<Process>| Self {
|
||||
pid,
|
||||
tasks: Mutex::new(TaskSet::new()),
|
||||
executable_file: RwLock::new(executable_file),
|
||||
vmar: Mutex::new(Some(vmar)),
|
||||
children_wait_queue,
|
||||
pidfile_pollee: Pollee::new(),
|
||||
|
|
@ -294,14 +288,6 @@ impl Process {
|
|||
&self.tasks
|
||||
}
|
||||
|
||||
pub fn executable_file(&self) -> PathOrInode {
|
||||
self.executable_file.read().clone()
|
||||
}
|
||||
|
||||
pub fn set_executable_file(&self, executable_file: PathOrInode) {
|
||||
*self.executable_file.write() = executable_file;
|
||||
}
|
||||
|
||||
pub fn resource_limits(&self) -> &ResourceLimits {
|
||||
&self.resource_limits
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub use self::{
|
|||
InitStack, InitStackReader, INIT_STACK_SIZE, MAX_LEN_STRING_ARG, MAX_NR_STRING_ARGS,
|
||||
},
|
||||
};
|
||||
use crate::{prelude::*, vm::vmar::Vmar};
|
||||
use crate::{fs::fs_resolver::PathOrInode, prelude::*, vm::vmar::Vmar};
|
||||
|
||||
/*
|
||||
* The user's virtual memory space layout looks like below.
|
||||
|
|
@ -68,6 +68,8 @@ pub struct ProcessVm {
|
|||
init_stack: InitStack,
|
||||
/// The user heap
|
||||
heap: Heap,
|
||||
/// The executable `PathOrInode`.
|
||||
executable_file: PathOrInode,
|
||||
/// The base address for vDSO segment
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
vdso_base: AtomicUsize,
|
||||
|
|
@ -75,10 +77,11 @@ pub struct ProcessVm {
|
|||
|
||||
impl ProcessVm {
|
||||
/// Creates a new `ProcessVm` without mapping anything.
|
||||
pub fn new() -> Self {
|
||||
fn new(executable_file: PathOrInode) -> Self {
|
||||
Self {
|
||||
init_stack: InitStack::new(),
|
||||
heap: Heap::new(),
|
||||
executable_file,
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
vdso_base: AtomicUsize::new(0),
|
||||
}
|
||||
|
|
@ -89,6 +92,7 @@ impl ProcessVm {
|
|||
Self {
|
||||
init_stack: process_vm.init_stack.clone(),
|
||||
heap: process_vm.heap.clone(),
|
||||
executable_file: process_vm.executable_file.clone(),
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
vdso_base: AtomicUsize::new(process_vm.vdso_base.load(Ordering::Relaxed)),
|
||||
}
|
||||
|
|
@ -104,6 +108,11 @@ impl ProcessVm {
|
|||
&self.heap
|
||||
}
|
||||
|
||||
/// Returns a reference to the executable `PathOrInode`.
|
||||
pub fn executable_file(&self) -> &PathOrInode {
|
||||
&self.executable_file
|
||||
}
|
||||
|
||||
/// Maps and writes the initial portion of the main stack of a process.
|
||||
pub(super) fn map_and_write_init_stack(
|
||||
&self,
|
||||
|
|
@ -194,8 +203,8 @@ impl<'a> ProcessVmarGuard<'a> {
|
|||
/// Creates a new VMAR and map the heap.
|
||||
///
|
||||
/// This method should only be used to create a VMAR for the init process.
|
||||
pub(super) fn new_vmar_and_map() -> Arc<Vmar> {
|
||||
let new_vmar = Vmar::new();
|
||||
pub(super) fn new_vmar_and_map(executable_file: PathOrInode) -> Arc<Vmar> {
|
||||
let new_vmar = Vmar::new(ProcessVm::new(executable_file));
|
||||
new_vmar
|
||||
.process_vm()
|
||||
.heap()
|
||||
|
|
@ -205,8 +214,12 @@ pub(super) fn new_vmar_and_map() -> Arc<Vmar> {
|
|||
}
|
||||
|
||||
/// Unshares and renews the [`Vmar`] of the current process.
|
||||
pub(super) fn unshare_and_renew_vmar(ctx: &Context, vmar: &mut ProcessVmarGuard) {
|
||||
let new_vmar = Vmar::new();
|
||||
pub(super) fn unshare_and_renew_vmar(
|
||||
ctx: &Context,
|
||||
vmar: &mut ProcessVmarGuard,
|
||||
executable_file: PathOrInode,
|
||||
) {
|
||||
let new_vmar = Vmar::new(ProcessVm::new(executable_file));
|
||||
let guard = disable_preempt();
|
||||
*ctx.thread_local.vmar().borrow_mut() = Some(new_vmar.clone());
|
||||
new_vmar.vm_space().activate();
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ pub fn handle_pending_signal(
|
|||
match sig_default_action {
|
||||
SigDefaultAction::Core | SigDefaultAction::Term => {
|
||||
warn!(
|
||||
"{:?}: terminating on signal {}",
|
||||
ctx.process.executable_file().display_name(),
|
||||
"PID {}: terminating on signal {}",
|
||||
ctx.process.pid(),
|
||||
sig_num.sig_name()
|
||||
);
|
||||
// We should exit current here, since we cannot restore a valid status from trap now.
|
||||
|
|
|
|||
|
|
@ -49,11 +49,10 @@ pub struct Vmar {
|
|||
|
||||
impl Vmar {
|
||||
/// Creates a new VMAR.
|
||||
pub fn new() -> Arc<Self> {
|
||||
pub fn new(process_vm: ProcessVm) -> Arc<Self> {
|
||||
let inner = VmarInner::new();
|
||||
let vm_space = VmSpace::new();
|
||||
let rss_counters = array::from_fn(|_| PerCpuCounter::new());
|
||||
let process_vm = ProcessVm::new();
|
||||
Arc::new(Vmar {
|
||||
inner: RwMutex::new(inner),
|
||||
vm_space: Arc::new(vm_space),
|
||||
|
|
|
|||
Loading…
Reference in New Issue