aya: Fix PerCpuHashMap NotFound

PerCpuHashMap was never returning MapError::KeyNotFound because
bpf_map_lookup_elem_per_cpu was replacing Ok(None) with
Ok(Some(zeroed_value)).

Update bpf_map_lookup_elem_per_cpu to map the Option value.
reviewable/pr1188/r1
aorhant 2 weeks ago committed by Tamir Duberstein
parent 39e40ba5c7
commit 9e1bcd0ab8

@ -151,12 +151,23 @@ impl<T: Borrow<MapData>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>>
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{ffi::c_long, io};
use assert_matches::assert_matches;
use aya_obj::generated::bpf_map_type::{ use aya_obj::generated::bpf_map_type::{
BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH, BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH,
}; };
use libc::ENOENT;
use super::*; use super::*;
use crate::maps::{test_utils, Map}; use crate::{
maps::{test_utils, Map},
sys::{override_syscall, SysResult},
};
fn sys_error(value: i32) -> SysResult<c_long> {
Err((-1, io::Error::from_raw_os_error(value)))
}
#[test] #[test]
fn test_try_from_ok() { fn test_try_from_ok() {
@ -174,4 +185,15 @@ mod tests {
let map = Map::PerCpuLruHashMap(map_data()); let map = Map::PerCpuLruHashMap(map_data());
assert!(PerCpuHashMap::<_, u32, u32>::try_from(&map).is_ok()) 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::<u32>(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));
}
} }

@ -249,7 +249,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu<K: Pod, V: Pod>(
) -> SysResult<Option<PerCpuValues<V>>> { ) -> SysResult<Option<PerCpuValues<V>>> {
let mut mem = PerCpuValues::<V>::alloc_kernel_mem().map_err(|io_error| (-1, io_error))?; let mut mem = PerCpuValues::<V>::alloc_kernel_mem().map_err(|io_error| (-1, io_error))?;
match bpf_map_lookup_elem_ptr(fd, Some(key), mem.as_mut_ptr(), flags) { 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((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
Err(e) => Err(e), Err(e) => Err(e),
} }

@ -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. /// Returns the numeric IDs of the CPUs currently online.
pub fn online_cpus() -> Result<Vec<u32>, (&'static str, io::Error)> { pub fn online_cpus() -> Result<Vec<u32>, (&'static str, io::Error)> {
const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online";
read_cpu_ranges(ONLINE_CPUS) read_cpu_ranges(ONLINE_CPUS)
} }
@ -194,14 +193,24 @@ pub fn online_cpus() -> Result<Vec<u32>, (&'static str, io::Error)> {
/// ///
/// See `/sys/devices/system/cpu/possible`. /// See `/sys/devices/system/cpu/possible`.
pub fn nr_cpus() -> Result<usize, (&'static str, io::Error)> { pub fn nr_cpus() -> Result<usize, (&'static str, io::Error)> {
const POSSIBLE_CPUS: &str = "/sys/devices/system/cpu/possible";
thread_local! { thread_local! {
// TODO(https://github.com/rust-lang/rust/issues/109737): Use // TODO(https://github.com/rust-lang/rust/issues/109737): Use
// `std::cell::OnceCell` when `get_or_try_init` is stabilized. // `std::cell::OnceCell` when `get_or_try_init` is stabilized.
static CACHE: once_cell::unsync::OnceCell<usize> = const { once_cell::unsync::OnceCell::new() }; static CACHE: once_cell::unsync::OnceCell<usize> = const { once_cell::unsync::OnceCell::new() };
} }
CACHE.with(|cell| { CACHE.with(|cell| {
cell.get_or_try_init(|| read_cpu_ranges(POSSIBLE_CPUS).map(|cpus| cpus.len())) cell.get_or_try_init(|| {
.copied() // 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()
}) })
} }

Loading…
Cancel
Save