diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index 37ec1b2c..52a89756 100644 --- a/aya-log/src/lib.rs +++ b/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(); diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index e9cad2b5..58e2f58d 100644 --- a/aya/src/bpf.rs +++ b/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 { - 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( diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index 5238da73..66e7f431 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/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 diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index 2dd8bcd7..54cbe118 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -105,10 +105,11 @@ impl, K: Pod, V: Pod> PerCpuHashMap { /// /// 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>(()) diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index e74289bb..6f36b6b3 100644 --- a/aya/src/maps/mod.rs +++ b/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 TryFrom> for PerCpuValues { type Error = io::Error; fn try_from(values: Vec) -> Result { - 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 TryFrom> for PerCpuValues { impl PerCpuValues { pub(crate) fn alloc_kernel_mem() -> Result { let value_size = (mem::size_of::() + 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::( 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::( 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::( crate::generated::bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY, diff --git a/aya/src/maps/perf/async_perf_event_array.rs b/aya/src/maps/perf/async_perf_event_array.rs index fff98456..6fcfcdf2 100644 --- a/aya/src/maps/perf/async_perf_event_array.rs +++ b/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)?; /// diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index f48826cc..47e37e95 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -122,7 +122,7 @@ impl> AsRawFd for PerfEventArrayBuffer { /// // 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)?); /// } diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs index b5c0727c..7777fc22 100644 --- a/aya/src/maps/xdp/cpu_map.rs +++ b/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); /// } /// diff --git a/aya/src/programs/perf_event.rs b/aya/src/programs/perf_event.rs index 00ac4b38..587d6499 100644 --- a/aya/src/programs/perf_event.rs +++ b/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, diff --git a/aya/src/util.rs b/aya/src/util.rs index 18de6002..d60309b2 100644 --- a/aya/src/util.rs +++ b/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, 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, (&'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 { - Ok(possible_cpus()?.len()) +pub fn nr_cpus() -> Result { + 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, 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, (&'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, ()> { +fn parse_cpu_ranges(data: &str) -> Result, &str> { let mut cpus = Vec::new(); for range in data.split(',') { cpus.extend({ @@ -226,10 +216,10 @@ fn parse_cpu_ranges(data: &str) -> Result, ()> { .splitn(2, '-') .map(u32::from_str) .collect::, _>>() - .map_err(|_| ())? + .map_err(|ParseIntError { .. }| range)? .as_slice() { - &[] | &[_, _, _, ..] => return Err(()), + &[] | &[_, _, _, ..] => return Err(range), &[start] => start..=start, &[start, end] => start..=end, } diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index c9ff22f4..4cf53afa 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -9026,8 +9026,8 @@ pub unsafe fn aya::util::KernelVersion::clone_to_uninit(&self, dst: *mut T) impl core::convert::From for aya::util::KernelVersion pub fn aya::util::KernelVersion::from(t: T) -> T pub fn aya::util::kernel_symbols() -> core::result::Result, std::io::error::Error> -pub fn aya::util::nr_cpus() -> core::result::Result -pub fn aya::util::online_cpus() -> core::result::Result, std::io::error::Error> +pub fn aya::util::nr_cpus() -> core::result::Result +pub fn aya::util::online_cpus() -> core::result::Result, (&'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