From 7d94174992016c6ae0dc7f9e52dccb3d1f9dab9d Mon Sep 17 00:00:00 2001 From: Krysztal Huang Date: Sat, 8 Nov 2025 03:25:59 +0800 Subject: [PATCH] pgrep: optimize get `Namespace` via `statx` syscall --- Cargo.lock | 25 +++++++------ Cargo.toml | 1 + src/uu/pgrep/Cargo.toml | 5 ++- src/uu/pgrep/src/process.rs | 75 +++++++++++++++++++++++++------------ 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41fb050..7993958 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -289,7 +289,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix 1.0.5", + "rustix 1.1.2", "signal-hook", "signal-hook-mio", "winapi", @@ -772,7 +772,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -841,9 +841,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litrs" @@ -1142,7 +1142,7 @@ dependencies = [ "chrono", "flate2", "procfs-core", - "rustix 1.0.5", + "rustix 1.1.2", ] [[package]] @@ -1359,15 +1359,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.5" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -1570,7 +1570,7 @@ dependencies = [ "fastrand", "getrandom 0.3.2", "once_cell", - "rustix 1.0.5", + "rustix 1.1.2", "windows-sys 0.61.2", ] @@ -1591,7 +1591,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 1.0.5", + "rustix 1.1.2", "windows-sys 0.60.2", ] @@ -1805,6 +1805,7 @@ version = "0.0.1" dependencies = [ "clap", "regex", + "rustix 1.1.2", "uucore 0.2.2", "walkdir", ] @@ -2564,7 +2565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.0.5", + "rustix 1.1.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c35c04c..fb335b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,6 +69,7 @@ prettytable-rs = "0.10.0" rand = { version = "0.9.0", features = ["small_rng"] } ratatui = "0.29.0" regex = "1.10.4" +rustix = { version = "1.1.2", features = ["fs"] } sysinfo = "0.37.0" tempfile = "3.10.1" terminal_size = "0.4.2" diff --git a/src/uu/pgrep/Cargo.toml b/src/uu/pgrep/Cargo.toml index 0d4b94d..7f71a9f 100644 --- a/src/uu/pgrep/Cargo.toml +++ b/src/uu/pgrep/Cargo.toml @@ -14,10 +14,11 @@ version.workspace = true workspace = true [dependencies] -uucore = { workspace = true, features = ["entries", "signals", "process"] } clap = { workspace = true } -walkdir = { workspace = true } regex = { workspace = true } +rustix = { workspace = true } +uucore = { workspace = true, features = ["entries", "signals", "process"] } +walkdir = { workspace = true } [lib] path = "src/pgrep.rs" diff --git a/src/uu/pgrep/src/process.rs b/src/uu/pgrep/src/process.rs index 724cc4d..721c424 100644 --- a/src/uu/pgrep/src/process.rs +++ b/src/uu/pgrep/src/process.rs @@ -218,15 +218,19 @@ impl TryFrom<&str> for CgroupMembership { } } -// See https://www.man7.org/linux/man-pages/man7/namespaces.7.html +/// See https://www.man7.org/linux/man-pages/man7/namespaces.7.html +/// +/// # Support status +/// +/// **_Linux only._** #[derive(Default)] pub struct Namespace { - pub ipc: Option, - pub mnt: Option, - pub net: Option, - pub pid: Option, - pub user: Option, - pub uts: Option, + pub ipc: Option, + pub mnt: Option, + pub net: Option, + pub pid: Option, + pub user: Option, + pub uts: Option, } impl Namespace { @@ -241,28 +245,51 @@ impl Namespace { } } - pub fn from_pid(pid: usize) -> Result { - let mut ns = Namespace::new(); - let path = PathBuf::from(format!("/proc/{pid}/ns")); - for entry in fs::read_dir(path)? { - let entry = entry?; - if let Some(name) = entry.file_name().to_str() { - if let Ok(value) = read_link(entry.path()) { - match name { - "ipc" => ns.ipc = Some(value.to_str().unwrap_or_default().to_string()), - "mnt" => ns.mnt = Some(value.to_str().unwrap_or_default().to_string()), - "net" => ns.net = Some(value.to_str().unwrap_or_default().to_string()), - "pid" => ns.pid = Some(value.to_str().unwrap_or_default().to_string()), - "user" => ns.user = Some(value.to_str().unwrap_or_default().to_string()), - "uts" => ns.uts = Some(value.to_str().unwrap_or_default().to_string()), - _ => {} - } - } + #[cfg(target_os = "linux")] + pub fn from_pid(pid: usize) -> io::Result { + use std::os::fd::OwnedFd; + + use rustix::fs::{openat, statx, AtFlags, Mode, OFlags, StatxFlags, CWD}; + + let f = |name: &str, fd: &OwnedFd| { + statx( + fd, + name, + AtFlags::empty(), // NO FOLLOW LINKS + StatxFlags::INO, // INNODE ONLY + ) + }; + + let ns_dir = openat( + CWD, + PathBuf::from(format!("/proc/{}/ns", pid)), + OFlags::RDONLY | OFlags::CLOEXEC, + Mode::empty(), + )?; + let mut ns = Namespace::default(); + + for (name, slot) in [ + ("ipc", &mut ns.ipc), + ("mnt", &mut ns.mnt), + ("net", &mut ns.net), + ("pid", &mut ns.pid), + ("user", &mut ns.user), + ("uts", &mut ns.uts), + ] { + match f(name, &ns_dir) { + Ok(st) => *slot = Some(st.stx_ino), + Err(e) => return Err(e.into()), } } Ok(ns) } + /// TODO: implementation for other system + #[cfg(not(target_os = "linux"))] + pub fn from_pid(_pid: usize) -> Result { + Ok(Namespace::new()) + } + pub fn filter(&mut self, filters: &[&str]) { if !filters.contains(&"ipc") { self.ipc = None;