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 d9194668..afb76620 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -151,12 +151,23 @@ impl, K: Pod, V: Pod> IterableMap> #[cfg(test)] mod tests { + use std::{ffi::c_long, io}; + + use assert_matches::assert_matches; use aya_obj::generated::bpf_map_type::{ BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH, }; + use libc::ENOENT; use super::*; - use crate::maps::{test_utils, Map}; + use crate::{ + maps::{test_utils, Map}, + sys::{override_syscall, SysResult}, + }; + + fn sys_error(value: i32) -> SysResult { + Err((-1, io::Error::from_raw_os_error(value))) + } #[test] fn test_try_from_ok() { @@ -174,4 +185,15 @@ mod tests { let map = Map::PerCpuLruHashMap(map_data()); assert!(PerCpuHashMap::<_, u32, u32>::try_from(&map).is_ok()) } + #[test] + fn test_get_not_found() { + let map_data = + || test_utils::new_map(test_utils::new_obj_map::(BPF_MAP_TYPE_LRU_PERCPU_HASH)); + let map = Map::PerCpuHashMap(map_data()); + let map = PerCpuHashMap::<_, u32, u32>::try_from(&map).unwrap(); + + override_syscall(|_| sys_error(ENOENT)); + + assert_matches!(map.get(&1, 0), Err(MapError::KeyNotFound)); + } } diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 791959f1..51ca7a97 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -249,7 +249,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu( ) -> SysResult>> { let mut mem = PerCpuValues::::alloc_kernel_mem().map_err(|io_error| (-1, io_error))?; match bpf_map_lookup_elem_ptr(fd, Some(key), mem.as_mut_ptr(), flags) { - Ok(_) => Ok(Some(unsafe { PerCpuValues::from_kernel_mem(mem) })), + Ok(v) => Ok(v.map(|()| unsafe { PerCpuValues::from_kernel_mem(mem) })), Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None), Err(e) => Err(e), } diff --git a/aya/src/util.rs b/aya/src/util.rs index 377ccc59..fbb9307f 100644 --- a/aya/src/util.rs +++ b/aya/src/util.rs @@ -182,11 +182,10 @@ impl Display for KernelVersion { } } -const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online"; -const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible"; - /// Returns the numeric IDs of the CPUs currently online. pub fn online_cpus() -> Result, (&'static str, io::Error)> { + const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online"; + read_cpu_ranges(ONLINE_CPUS) } @@ -194,14 +193,24 @@ pub fn online_cpus() -> Result, (&'static str, io::Error)> { /// /// See `/sys/devices/system/cpu/possible`. pub fn nr_cpus() -> Result { + const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible"; + thread_local! { // TODO(https://github.com/rust-lang/rust/issues/109737): Use // `std::cell::OnceCell` when `get_or_try_init` is stabilized. static CACHE: once_cell::unsync::OnceCell = const { once_cell::unsync::OnceCell::new() }; } CACHE.with(|cell| { - cell.get_or_try_init(|| read_cpu_ranges(POSSIBLE_CPUS).map(|cpus| cpus.len())) - .copied() + cell.get_or_try_init(|| { + // error: unsupported operation: `open` not available when isolation is enabled + if cfg!(miri) { + parse_cpu_ranges("0-3").map_err(|error| (POSSIBLE_CPUS, error)) + } else { + read_cpu_ranges(POSSIBLE_CPUS) + } + .map(|cpus| cpus.len()) + }) + .copied() }) }