Reduce duplication in `{nr,possible}_cpus`

pull/1043/head
Tamir Duberstein 4 months ago
parent 2b299d4fba
commit f3b2744072

@ -161,7 +161,7 @@ impl EbpfLogger {
let mut logs: AsyncPerfEventArray<_> = map.try_into()?; let mut logs: AsyncPerfEventArray<_> = map.try_into()?;
let logger = Arc::new(logger); 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 mut buf = logs.open(cpu_id, None)?;
let log = logger.clone(); let log = logger.clone();

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

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

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

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

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

@ -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 /// // 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. /// // running on as the array index.
/// let mut perf_buffers = Vec::new(); /// 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 /// // this perf buffer will receive events generated on the CPU with id cpu_id
/// perf_buffers.push(perf_array.open(cpu_id, None)?); /// perf_buffers.push(perf_array.open(cpu_id, None)?);
/// } /// }

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

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

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

@ -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 impl<T> core::convert::From<T> for aya::util::KernelVersion
pub fn aya::util::KernelVersion::from(t: T) -> T 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::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::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>, 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 fn aya::util::syscall_prefix() -> core::result::Result<&'static str, std::io::error::Error>
pub macro aya::include_bytes_aligned! pub macro aya::include_bytes_aligned!
pub enum aya::EbpfError pub enum aya::EbpfError

Loading…
Cancel
Save