diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index d22f0af5b5..a75638a5f3 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -173,6 +173,9 @@ enum ContextHandle { ProcMaps { pid: usize, }, + ProcStatm { + pid: usize, + }, } #[derive(Clone)] struct Handle { @@ -393,6 +396,7 @@ impl ProcScheme { (Some("cmdline"), None) => Some(ContextHandle::ProcCmdline { pid }), (Some("status"), None) => Some(ContextHandle::ProcStatus { pid }), (Some("maps"), None) => Some(ContextHandle::ProcMaps { pid }), + (Some("statm"), None) => Some(ContextHandle::ProcStatm { pid }), _ => None, } } @@ -1930,6 +1934,34 @@ impl ContextHandle { } read_from(buf, output.as_bytes(), offset) } + ContextHandle::ProcStatm { pid } => { + let context = proc_context(*pid, token).ok_or(Error::new(ESRCH))?; + let addr_space = context.read(token.token()).addr_space.clone(); + let (size, resident) = if let Some(addr_space) = addr_space { + let token2 = token.downgrade(); + let guard = addr_space.acquire_read(token2); + let mut total_size = 0usize; + let mut total_resident = 0usize; + for (_grant_base, grant_info) in guard.grants.iter() { + let page_count = grant_info.page_count() * PAGE_SIZE; + total_size += page_count; + if grant_info.grant_flags().contains(GrantFlags::GRANT_PHYS) { + total_resident += page_count; + } + } + (total_size / PAGE_SIZE, total_resident / PAGE_SIZE) + } else { + (0, 0) + }; + // Format: size resident shared text lib data dt (in pages) + // Cross-referenced with Linux 7.1 fs/proc/array.c:proc_pid_statm(). + // On Red Bear we approximate: shared=0, text=size, lib=0, data=size, dt=0. + let output = alloc::format!( + "{} {} 0 {} 0 {} 0\n", + size, resident, size, size + ); + read_from(buf, output.as_bytes(), offset) + } ContextHandle::ProcRoot | ContextHandle::ProcDir { .. } => Err(Error::new(EBADF)), ContextHandle::MmapMinAddr(addrspace) => { let mut token = token.token();