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}