Bläddra i källkod

Reduce duplication in `{nr,possible}_cpus`

Tamir Duberstein 5 månader sedan
förälder
incheckning
f3b2744072

+ 1 - 1
aya-log/src/lib.rs

@@ -161,7 +161,7 @@ impl EbpfLogger {
         let mut logs: AsyncPerfEventArray<_> = map.try_into()?;
 
         let logger = Arc::new(logger);
-        for cpu_id in online_cpus().map_err(Error::InvalidOnlineCpu)? {
+        for cpu_id in online_cpus().map_err(|(_, error)| Error::InvalidOnlineCpu(error))? {
             let mut buf = logs.open(cpu_id, None)?;
 
             let log = logger.clone();

+ 6 - 8
aya/src/bpf.rs

@@ -43,7 +43,7 @@ use crate::{
         is_info_map_ids_supported, is_perf_link_supported, is_probe_read_kernel_supported,
         is_prog_id_supported, is_prog_name_supported, retry_with_verifier_logs,
     },
-    util::{bytes_of, bytes_of_slice, page_size, possible_cpus, POSSIBLE_CPUS},
+    util::{bytes_of, bytes_of_slice, nr_cpus, page_size},
 };
 
 pub(crate) const BPF_OBJ_NAME_LEN: usize = 16;
@@ -465,13 +465,11 @@ impl<'a> EbpfLoader<'a> {
             {
                 continue;
             }
-            let num_cpus = || -> Result<u32, EbpfError> {
-                Ok(possible_cpus()
-                    .map_err(|error| EbpfError::FileError {
-                        path: PathBuf::from(POSSIBLE_CPUS),
-                        error,
-                    })?
-                    .len() as u32)
+            let num_cpus = || {
+                Ok(nr_cpus().map_err(|(path, error)| EbpfError::FileError {
+                    path: PathBuf::from(path),
+                    error,
+                })? as u32)
             };
             let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?;
             if let Some(max_entries) = max_entries_override(

+ 1 - 1
aya/src/maps/array/per_cpu_array.rs

@@ -37,7 +37,7 @@ use crate::{
 /// let mut array = PerCpuArray::try_from(bpf.map_mut("ARRAY").unwrap())?;
 ///
 /// // set array[1] = 42 for all cpus
-/// let nr_cpus = nr_cpus()?;
+/// let nr_cpus = nr_cpus().map_err(|(_, error)| error)?;
 /// array.set(1, PerCpuValues::try_from(vec![42u32; nr_cpus])?, 0)?;
 ///
 /// // retrieve the values at index 1 for all cpus

+ 2 - 1
aya/src/maps/hash_map/per_cpu_hash_map.rs

@@ -105,10 +105,11 @@ impl<T: BorrowMut<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
     ///
     /// const RETRIES: u8 = 1;
     ///
+    /// let nr_cpus = nr_cpus().map_err(|(_, error)| error)?;
     /// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map_mut("PER_CPU_STORAGE").unwrap())?;
     /// hm.insert(
     ///     RETRIES,
-    ///     PerCpuValues::try_from(vec![3u32; nr_cpus()?])?,
+    ///     PerCpuValues::try_from(vec![3u32; nr_cpus])?,
     ///     0,
     /// )?;
     /// # Ok::<(), Error>(())

+ 14 - 12
aya/src/maps/mod.rs

@@ -569,9 +569,9 @@ impl MapData {
         //
         // Otherwise, when the value is `0` or too large, we set it to the number of CPUs.
         if obj.map_type() == bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 {
-            let ncpus = nr_cpus().map_err(MapError::IoError)? as u32;
-            if obj.max_entries() == 0 || obj.max_entries() > ncpus {
-                obj.set_max_entries(ncpus);
+            let nr_cpus = nr_cpus().map_err(|(_, error)| MapError::IoError(error))? as u32;
+            if obj.max_entries() == 0 || obj.max_entries() > nr_cpus {
+                obj.set_max_entries(nr_cpus);
             }
         };
 
@@ -879,7 +879,8 @@ impl PerCpuKernelMem {
 /// use aya::maps::PerCpuValues;
 /// use aya::util::nr_cpus;
 ///
-/// let values = PerCpuValues::try_from(vec![42u32; nr_cpus()?])?;
+/// let nr_cpus = nr_cpus().map_err(|(_, error)| error)?;
+/// let values = PerCpuValues::try_from(vec![42u32; nr_cpus])?;
 /// # Ok::<(), Error>(())
 /// ```
 #[derive(Debug)]
@@ -891,7 +892,7 @@ impl<T: Pod> TryFrom<Vec<T>> for PerCpuValues<T> {
     type Error = io::Error;
 
     fn try_from(values: Vec<T>) -> Result<Self, Self::Error> {
-        let nr_cpus = nr_cpus()?;
+        let nr_cpus = nr_cpus().map_err(|(_, error)| error)?;
         if values.len() != nr_cpus {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidInput,
@@ -907,8 +908,9 @@ impl<T: Pod> TryFrom<Vec<T>> for PerCpuValues<T> {
 impl<T: Pod> PerCpuValues<T> {
     pub(crate) fn alloc_kernel_mem() -> Result<PerCpuKernelMem, io::Error> {
         let value_size = (mem::size_of::<T>() + 7) & !7;
+        let nr_cpus = nr_cpus().map_err(|(_, error)| error)?;
         Ok(PerCpuKernelMem {
-            bytes: vec![0u8; nr_cpus()? * value_size],
+            bytes: vec![0u8; nr_cpus * value_size],
         })
     }
 
@@ -1086,9 +1088,9 @@ mod tests {
             _ => Err((-1, io::Error::from_raw_os_error(EFAULT))),
         });
 
-        let ncpus = nr_cpus().unwrap();
+        let nr_cpus = nr_cpus().unwrap();
 
-        // Create with max_entries > ncpus is clamped to ncpus
+        // Create with max_entries > nr_cpus is clamped to nr_cpus
         assert_matches!(
             MapData::create(test_utils::new_obj_map_with_max_entries::<u32>(
                 crate::generated::bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY,
@@ -1099,11 +1101,11 @@ mod tests {
                 fd,
             }) => {
                 assert_eq!(fd.as_fd().as_raw_fd(), crate::MockableFd::mock_signed_fd());
-                assert_eq!(obj.max_entries(), ncpus as u32)
+                assert_eq!(obj.max_entries(), nr_cpus as u32)
             }
         );
 
-        // Create with max_entries = 0 is set to ncpus
+        // Create with max_entries = 0 is set to nr_cpus
         assert_matches!(
             MapData::create(test_utils::new_obj_map_with_max_entries::<u32>(
                 crate::generated::bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY,
@@ -1114,11 +1116,11 @@ mod tests {
                 fd,
             }) => {
                 assert_eq!(fd.as_fd().as_raw_fd(), crate::MockableFd::mock_signed_fd());
-                assert_eq!(obj.max_entries(), ncpus as u32)
+                assert_eq!(obj.max_entries(), nr_cpus as u32)
             }
         );
 
-        // Create with max_entries < ncpus is unchanged
+        // Create with max_entries < nr_cpus is unchanged
         assert_matches!(
             MapData::create(test_utils::new_obj_map_with_max_entries::<u32>(
                 crate::generated::bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY,

+ 1 - 1
aya/src/maps/perf/async_perf_event_array.rs

@@ -57,7 +57,7 @@ use crate::maps::{
 /// // try to convert the PERF_ARRAY map to an AsyncPerfEventArray
 /// let mut perf_array = AsyncPerfEventArray::try_from(bpf.take_map("PERF_ARRAY").unwrap())?;
 ///
-/// for cpu_id in online_cpus()? {
+/// for cpu_id in online_cpus().map_err(|(_, error)| error)? {
 ///     // open a separate perf buffer for each cpu
 ///     let mut buf = perf_array.open(cpu_id, None)?;
 ///

+ 1 - 1
aya/src/maps/perf/perf_event_array.rs

@@ -122,7 +122,7 @@ impl<T: BorrowMut<MapData>> AsRawFd for PerfEventArrayBuffer<T> {
 /// // eBPF programs are going to write to the EVENTS perf array, using the id of the CPU they're
 /// // running on as the array index.
 /// let mut perf_buffers = Vec::new();
-/// for cpu_id in online_cpus()? {
+/// for cpu_id in online_cpus().map_err(|(_, error)| error)? {
 ///     // this perf buffer will receive events generated on the CPU with id cpu_id
 ///     perf_buffers.push(perf_array.open(cpu_id, None)?);
 /// }

+ 4 - 3
aya/src/maps/xdp/cpu_map.rs

@@ -29,16 +29,17 @@ use crate::{
 /// ```no_run
 /// # let elf_bytes = &[];
 /// use aya::maps::xdp::CpuMap;
+/// use aya::util::nr_cpus;
 ///
-/// let ncpus = aya::util::nr_cpus().unwrap() as u32;
+/// let nr_cpus = nr_cpus().unwrap() as u32;
 /// let mut bpf = aya::EbpfLoader::new()
-///     .set_max_entries("CPUS", ncpus)
+///     .set_max_entries("CPUS", nr_cpus)
 ///     .load(elf_bytes)
 ///     .unwrap();
 /// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS").unwrap())?;
 /// let flags = 0;
 /// let queue_size = 2048;
-/// for i in 0..ncpus {
+/// for i in 0..nr_cpus {
 ///     cpumap.set(i, queue_size, None, flags);
 /// }
 ///

+ 1 - 1
aya/src/programs/perf_event.rs

@@ -109,7 +109,7 @@ pub enum PerfEventScope {
 /// let prog: &mut PerfEvent = bpf.program_mut("observe_cpu_clock").unwrap().try_into()?;
 /// prog.load()?;
 ///
-/// for cpu in online_cpus()? {
+/// for cpu in online_cpus().map_err(|(_, error)| error)? {
 ///     prog.attach(
 ///         PerfTypeId::Software,
 ///         PERF_COUNT_SW_CPU_CLOCK as u64,

+ 15 - 25
aya/src/util.rs

@@ -185,40 +185,30 @@ impl Display for KernelVersion {
 }
 
 const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online";
-pub(crate) const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible";
+const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible";
 
 /// Returns the numeric IDs of the CPUs currently online.
-pub fn online_cpus() -> Result<Vec<u32>, io::Error> {
-    let data = fs::read_to_string(ONLINE_CPUS)?;
-    parse_cpu_ranges(data.trim()).map_err(|_| {
-        io::Error::new(
-            io::ErrorKind::Other,
-            format!("unexpected {ONLINE_CPUS} format"),
-        )
-    })
+pub fn online_cpus() -> Result<Vec<u32>, (&'static str, io::Error)> {
+    read_cpu_ranges(ONLINE_CPUS)
 }
 
 /// Get the number of possible cpus.
 ///
 /// See `/sys/devices/system/cpu/possible`.
-pub fn nr_cpus() -> Result<usize, io::Error> {
-    Ok(possible_cpus()?.len())
+pub fn nr_cpus() -> Result<usize, (&'static str, io::Error)> {
+    read_cpu_ranges(POSSIBLE_CPUS).map(|cpus| cpus.len())
 }
 
-/// Get the list of possible cpus.
-///
-/// See `/sys/devices/system/cpu/possible`.
-pub(crate) fn possible_cpus() -> Result<Vec<u32>, io::Error> {
-    let data = fs::read_to_string(POSSIBLE_CPUS)?;
-    parse_cpu_ranges(data.trim()).map_err(|_| {
-        io::Error::new(
-            io::ErrorKind::Other,
-            format!("unexpected {POSSIBLE_CPUS} format"),
-        )
-    })
+fn read_cpu_ranges(path: &'static str) -> Result<Vec<u32>, (&'static str, io::Error)> {
+    (|| {
+        let data = fs::read_to_string(path)?;
+        parse_cpu_ranges(data.trim())
+            .map_err(|range| io::Error::new(io::ErrorKind::InvalidData, range))
+    })()
+    .map_err(|error| (path, error))
 }
 
-fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, ()> {
+fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, &str> {
     let mut cpus = Vec::new();
     for range in data.split(',') {
         cpus.extend({
@@ -226,10 +216,10 @@ fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, ()> {
                 .splitn(2, '-')
                 .map(u32::from_str)
                 .collect::<Result<Vec<_>, _>>()
-                .map_err(|_| ())?
+                .map_err(|ParseIntError { .. }| range)?
                 .as_slice()
             {
-                &[] | &[_, _, _, ..] => return Err(()),
+                &[] | &[_, _, _, ..] => return Err(range),
                 &[start] => start..=start,
                 &[start, end] => start..=end,
             }

+ 2 - 2
xtask/public-api/aya.txt

@@ -9026,8 +9026,8 @@ pub unsafe fn aya::util::KernelVersion::clone_to_uninit(&self, dst: *mut T)
 impl<T> core::convert::From<T> for aya::util::KernelVersion
 pub fn aya::util::KernelVersion::from(t: T) -> T
 pub fn aya::util::kernel_symbols() -> core::result::Result<alloc::collections::btree::map::BTreeMap<u64, alloc::string::String>, std::io::error::Error>
-pub fn aya::util::nr_cpus() -> core::result::Result<usize, std::io::error::Error>
-pub fn aya::util::online_cpus() -> core::result::Result<alloc::vec::Vec<u32>, std::io::error::Error>
+pub fn aya::util::nr_cpus() -> core::result::Result<usize, (&'static str, std::io::error::Error)>
+pub fn aya::util::online_cpus() -> core::result::Result<alloc::vec::Vec<u32>, (&'static str, std::io::error::Error)>
 pub fn aya::util::syscall_prefix() -> core::result::Result<&'static str, std::io::error::Error>
 pub macro aya::include_bytes_aligned!
 pub enum aya::EbpfError