perf_event_open/sample/record/
ns.rs

1use super::{RecordId, Task};
2
3/// Namespace information for the new task.
4///
5/// # Examples
6///
7/// ```rust, no_run
8/// use perf_event_open::config::{Cpu, Opts, Proc};
9/// use perf_event_open::count::Counter;
10/// use perf_event_open::event::sw::Software;
11///
12/// let event = Software::Dummy;
13/// let target = (Proc::CURRENT, Cpu::ALL);
14///
15/// let mut opts = Opts::default();
16/// opts.extra_record.namespaces = true;
17///
18/// let counter = Counter::new(event, target, opts).unwrap();
19/// let sampler = counter.sampler(5).unwrap();
20///
21/// counter.enable().unwrap();
22///
23/// // Captures the namespace information for this task.
24/// std::thread::spawn(|| {});
25///
26/// for it in sampler.iter() {
27///     println!("{:-?}", it);
28/// }
29/// ```
30///
31/// Since `linux-4.12`: <https://github.com/torvalds/linux/commit/e422267322cd319e2695a535e47c5b1feeac45eb>
32#[derive(Clone)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct Namespaces {
35    /// Record IDs.
36    pub record_id: Option<RecordId>,
37
38    /// Task info.
39    pub task: Task,
40    // UTS namespace link info.
41    pub ns_uts: LinkInfo,
42    // PID namespace link info.
43    pub ns_pid: LinkInfo,
44    // IPC namespace link info.
45    pub ns_ipc: LinkInfo,
46    // Mount namespace link info.
47    pub ns_mnt: LinkInfo,
48    // Network namespace link info.
49    pub ns_net: LinkInfo,
50    // User namespace link info.
51    pub ns_user: LinkInfo,
52    // Cgroup namespace link info.
53    pub ns_cgroup: LinkInfo,
54}
55
56impl Namespaces {
57    #[cfg(feature = "linux-4.12")]
58    pub(crate) unsafe fn from_ptr(
59        mut ptr: *const u8,
60        sample_id_all: Option<super::SampleType>,
61    ) -> Self {
62        use super::SampleType;
63        use crate::ffi::{bindings as b, deref_offset};
64
65        // https://github.com/torvalds/linux/blob/v6.13/include/uapi/linux/perf_event.h#L1141
66        // struct {
67        //     struct perf_event_header header;
68        //     u32 pid;
69        //     u32 tid;
70        //     u64 nr_namespaces;
71        //     { u64 dev, inode; } [nr_namespaces];
72        //     struct sample_id sample_id;
73        // }
74
75        let task = Task {
76            pid: deref_offset(&mut ptr),
77            tid: deref_offset(&mut ptr),
78        };
79
80        #[repr(C)]
81        #[derive(Clone, Copy)]
82        struct Layout {
83            dev: u64,
84            inode: u64,
85        }
86        impl From<Layout> for LinkInfo {
87            fn from(value: Layout) -> Self {
88                Self {
89                    dev: value.dev,
90                    inode: value.inode,
91                }
92            }
93        }
94        let nss: [Layout; b::NR_NAMESPACES as _] = deref_offset(&mut ptr);
95
96        let record_id = sample_id_all.map(|SampleType(ty)| RecordId::from_ptr(ptr, ty));
97
98        Self {
99            record_id,
100            task,
101            ns_net: nss[b::NET_NS_INDEX as usize].into(),
102            ns_uts: nss[b::UTS_NS_INDEX as usize].into(),
103            ns_ipc: nss[b::IPC_NS_INDEX as usize].into(),
104            ns_pid: nss[b::PID_NS_INDEX as usize].into(),
105            ns_user: nss[b::USER_NS_INDEX as usize].into(),
106            ns_mnt: nss[b::MNT_NS_INDEX as usize].into(),
107            ns_cgroup: nss[b::CGROUP_NS_INDEX as usize].into(),
108        }
109    }
110}
111
112super::from!(Namespaces);
113
114super::debug!(Namespaces {
115    {record_id?},
116    {task},
117    {ns_net},
118    {ns_uts},
119    {ns_ipc},
120    {ns_pid},
121    {ns_user},
122    {ns_mnt},
123    {ns_cgroup},
124});
125
126// Naming: https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L8590
127/// Namespace link info.
128#[derive(Clone, Debug)]
129#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
130pub struct LinkInfo {
131    /// Device number.
132    pub dev: u64,
133
134    /// Inode number.
135    pub inode: u64,
136}