reviewable/pr1251/r15
Tamir Duberstein 6 months ago
parent 3eea9a90b8
commit e8d8bf18ad
No known key found for this signature in database

@ -60,7 +60,7 @@ use std::{
}; };
use aya_obj::{EbpfSectionKind, InvalidTypeBinding, generated::bpf_map_type, parse_map_info}; use aya_obj::{EbpfSectionKind, InvalidTypeBinding, generated::bpf_map_type, parse_map_info};
use libc::{RLIM_INFINITY, RLIMIT_MEMLOCK, getrlimit, rlim_t, rlimit}; use libc::{RLIM_INFINITY, RLIMIT_MEMLOCK, getrlimit, rlim_t, rlimit, setrlimit};
use log::warn; use log::warn;
use thiserror::Error; use thiserror::Error;
@ -235,40 +235,6 @@ impl AsFd for MapFd {
} }
} }
/// Raises a warning about rlimit. Should be used only if creating a map was not
/// successful.
fn maybe_warn_rlimit() {
let mut limit = mem::MaybeUninit::<rlimit>::uninit();
let ret = unsafe { getrlimit(RLIMIT_MEMLOCK, limit.as_mut_ptr()) };
if ret == 0 {
let limit = unsafe { limit.assume_init() };
if limit.rlim_cur == RLIM_INFINITY {
return;
}
struct HumanSize(rlim_t);
impl fmt::Display for HumanSize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let &Self(size) = self;
if size < 1024 {
write!(f, "{size} bytes")
} else if size < 1024 * 1024 {
write!(f, "{} KiB", size / 1024)
} else {
write!(f, "{} MiB", size / 1024 / 1024)
}
}
}
warn!(
"RLIMIT_MEMLOCK value is {}, not RLIM_INFINITY; if experiencing problems with creating \
maps, try raising RLIMIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \
for the size of your maps",
HumanSize(limit.rlim_cur)
);
}
}
/// eBPF map types. /// eBPF map types.
#[derive(Debug)] #[derive(Debug)]
pub enum Map { pub enum Map {
@ -576,15 +542,58 @@ impl MapData {
} }
}; };
let fd = bpf_create_map(&c_name, &obj, btf_fd).map_err(|io_error| { let create_map = || bpf_create_map(&c_name, &obj, btf_fd);
if !KernelVersion::at_least(5, 11, 0) { let mut fd = create_map();
maybe_warn_rlimit(); if let Err(err) = fd.as_ref() {
} if err.raw_os_error() == Some(libc::EPERM) && !KernelVersion::at_least(5, 11, 0) {
(|| {
let mut limit = mem::MaybeUninit::<rlimit>::uninit();
let ret = unsafe { getrlimit(RLIMIT_MEMLOCK, limit.as_mut_ptr()) };
if ret != 0 {
warn!("getrlimit(RLIMIT_MEMLOCK) failed: {ret}");
return;
}
let rlimit {
rlim_cur,
rlim_max: _,
} = unsafe { limit.assume_init() };
MapError::CreateError { if rlim_cur == RLIM_INFINITY {
name: name.into(), return;
io_error, }
let limit = rlimit {
rlim_cur: RLIM_INFINITY,
rlim_max: RLIM_INFINITY,
};
let ret = unsafe { setrlimit(RLIMIT_MEMLOCK, &limit) };
if ret != 0 {
struct HumanSize(rlim_t);
impl fmt::Display for HumanSize {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let &Self(size) = self;
if size < 1024 {
write!(f, "{size} bytes")
} else if size < 1024 * 1024 {
write!(f, "{} KiB", size / 1024)
} else {
write!(f, "{} MiB", size / 1024 / 1024)
}
}
}
warn!(
"setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITIY) failed: {ret}; current value is {}",
HumanSize(rlim_cur)
);
return;
}
fd = create_map();
})();
} }
};
let fd = fd.map_err(|io_error| MapError::CreateError {
name: name.into(),
io_error,
})?; })?;
Ok(Self { Ok(Self {
obj, obj,

Loading…
Cancel
Save