aya: allow specifying a pin path for a named map

This commit extends the EbpfLoader with set_map_pin_path that allows the
caller to associate a named map with a pin path.

One note is that this path is an absolute path, not relative to
`map_pin_path`, and it forces the map to be loaded from that path.
reviewable/pr1371/r1
Andrew Werner 3 weeks ago committed by ajwerner
parent 1c924bb421
commit 5802dc7a23

@ -123,6 +123,10 @@ pub struct EbpfLoader<'a> {
// Max entries overrides the max_entries field of the map that matches the provided name // Max entries overrides the max_entries field of the map that matches the provided name
// before the map is created. // before the map is created.
max_entries: HashMap<&'a str, u32>, max_entries: HashMap<&'a str, u32>,
// Map pin path overrides the pin path of the map that matches the provided name before
// it is created.
map_pin_path_by_name: HashMap<&'a str, std::borrow::Cow<'a, Path>>,
extensions: HashSet<&'a str>, extensions: HashSet<&'a str>,
verifier_log_level: VerifierLogLevel, verifier_log_level: VerifierLogLevel,
allow_unsupported_maps: bool, allow_unsupported_maps: bool,
@ -161,6 +165,7 @@ impl<'a> EbpfLoader<'a> {
default_map_pin_directory: None, default_map_pin_directory: None,
globals: HashMap::new(), globals: HashMap::new(),
max_entries: HashMap::new(), max_entries: HashMap::new(),
map_pin_path_by_name: HashMap::new(),
extensions: HashSet::new(), extensions: HashSet::new(),
verifier_log_level: VerifierLogLevel::default(), verifier_log_level: VerifierLogLevel::default(),
allow_unsupported_maps: false, allow_unsupported_maps: false,
@ -218,6 +223,9 @@ impl<'a> EbpfLoader<'a> {
/// Pinned maps will be loaded from `path/MAP_NAME`. /// Pinned maps will be loaded from `path/MAP_NAME`.
/// The caller is responsible for ensuring the directory exists. /// The caller is responsible for ensuring the directory exists.
/// ///
/// Note that if a path is provided for a specific map via [`EbpfLoader::map_pin_path`],
/// it will take precedence over this path.
///
/// # Example /// # Example
/// ///
/// ```no_run /// ```no_run
@ -304,6 +312,33 @@ impl<'a> EbpfLoader<'a> {
self self
} }
/// Set the pin path for the map that matches the provided name.
///
/// Note that this is an absolute path to the pinned map; it is not a prefix
/// to be combined with the map name, and it is not relative to the
/// configured base directory for pinned maps.
///
/// Each call to this function with the same name overwrites the path to the
/// pinned map; last one wins.
///
/// # Example
///
/// ```no_run
/// # use std::path::Path;
///
/// # let mut loader = aya::EbpfLoader::new();
/// # let pin_path = Path::new("/sys/fs/bpf/my-pinned-map");
/// let bpf = loader
/// .map_pin_path("map", pin_path)
/// .load_file("file.o")?;
/// # Ok::<(), aya::EbpfError>(())
/// ```
///
pub fn map_pin_path<P: Into<Cow<'a, Path>>>(&mut self, name: &'a str, path: P) -> &mut Self {
self.map_pin_path_by_name.insert(name, path.into());
self
}
/// Treat the provided program as an [`Extension`] /// Treat the provided program as an [`Extension`]
/// ///
/// When attempting to load the program with the provided `name` /// When attempting to load the program with the provided `name`
@ -387,6 +422,7 @@ impl<'a> EbpfLoader<'a> {
extensions, extensions,
verifier_log_level, verifier_log_level,
allow_unsupported_maps, allow_unsupported_maps,
map_pin_path_by_name,
} = self; } = self;
let mut obj = Object::parse(data)?; let mut obj = Object::parse(data)?;
obj.patch_map_data(globals.clone())?; obj.patch_map_data(globals.clone())?;
@ -491,16 +527,21 @@ impl<'a> EbpfLoader<'a> {
_ => (), _ => (),
} }
let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd());
let mut map = match obj.pinning() { let mut map = if let Some(pin_path) = map_pin_path_by_name.get(name.as_str()) {
PinningType::None => MapData::create(obj, &name, btf_fd)?, MapData::create_pinned_by_name(pin_path, obj, &name, btf_fd)?
PinningType::ByName => { } else {
// pin maps in /sys/fs/bpf by default to align with libbpf match obj.pinning() {
// behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161. PinningType::None => MapData::create(obj, &name, btf_fd)?,
let path = default_map_pin_directory PinningType::ByName => {
.as_deref() // pin maps in /sys/fs/bpf by default to align with libbpf
.unwrap_or_else(|| Path::new("/sys/fs/bpf")); // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161.
let path = default_map_pin_directory
MapData::create_pinned_by_name(path, obj, &name, btf_fd)? .as_deref()
.unwrap_or_else(|| Path::new("/sys/fs/bpf"));
let path = path.join(&name);
MapData::create_pinned_by_name(path, obj, &name, btf_fd)?
}
} }
}; };
map.finalize()?; map.finalize()?;

@ -616,13 +616,16 @@ impl MapData {
use std::os::unix::ffi::OsStrExt as _; use std::os::unix::ffi::OsStrExt as _;
// try to open map in case it's already pinned // try to open map in case it's already pinned
let path = path.as_ref().join(name); let path = path.as_ref();
let path_string = match CString::new(path.as_os_str().as_bytes()) { let path_string = match CString::new(path.as_os_str().as_bytes()) {
Ok(path) => path, Ok(path) => path,
Err(error) => { Err(error) => {
return Err(MapError::PinError { return Err(MapError::PinError {
name: Some(name.into()), name: Some(name.into()),
error: PinError::InvalidPinPath { path, error }, error: PinError::InvalidPinPath {
path: path.to_path_buf(),
error,
},
}); });
} }
}; };
@ -636,7 +639,7 @@ impl MapData {
}), }),
Err(_) => { Err(_) => {
let map = Self::create(obj, name, btf_fd)?; let map = Self::create(obj, name, btf_fd)?;
map.pin(&path).map_err(|error| MapError::PinError { map.pin(path).map_err(|error| MapError::PinError {
name: Some(name.into()), name: Some(name.into()),
error, error,
})?; })?;

@ -10746,6 +10746,7 @@ pub fn aya::EbpfLoader<'a>::default_map_pin_directory<P: core::convert::AsRef<st
pub fn aya::EbpfLoader<'a>::extension(&mut self, name: &'a str) -> &mut Self pub fn aya::EbpfLoader<'a>::extension(&mut self, name: &'a str) -> &mut Self
pub fn aya::EbpfLoader<'a>::load(&mut self, data: &[u8]) -> core::result::Result<aya::Ebpf, aya::EbpfError> pub fn aya::EbpfLoader<'a>::load(&mut self, data: &[u8]) -> core::result::Result<aya::Ebpf, aya::EbpfError>
pub fn aya::EbpfLoader<'a>::load_file<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<aya::Ebpf, aya::EbpfError> pub fn aya::EbpfLoader<'a>::load_file<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<aya::Ebpf, aya::EbpfError>
pub fn aya::EbpfLoader<'a>::map_pin_path<P: core::convert::Into<alloc::borrow::Cow<'a, std::path::Path>>>(&mut self, name: &'a str, path: P) -> &mut Self
pub fn aya::EbpfLoader<'a>::new() -> Self pub fn aya::EbpfLoader<'a>::new() -> Self
pub fn aya::EbpfLoader<'a>::set_global<T: core::convert::Into<aya::GlobalData<'a>>>(&mut self, name: &'a str, value: T, must_exist: bool) -> &mut Self pub fn aya::EbpfLoader<'a>::set_global<T: core::convert::Into<aya::GlobalData<'a>>>(&mut self, name: &'a str, value: T, must_exist: bool) -> &mut Self
pub fn aya::EbpfLoader<'a>::set_max_entries(&mut self, name: &'a str, size: u32) -> &mut Self pub fn aya::EbpfLoader<'a>::set_max_entries(&mut self, name: &'a str, size: u32) -> &mut Self

Loading…
Cancel
Save