diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 163ce127f..191c58834 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -409,8 +409,6 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { pub struct MapData { obj: obj::Map, fd: MapFd, - /// Indicates if this map has been pinned to bpffs - pub pinned: bool, } impl MapData { @@ -439,11 +437,7 @@ impl MapData { } })?; let fd = MapFd(fd); - Ok(Self { - obj, - fd, - pinned: false, - }) + Ok(Self { obj, fd }) } pub(crate) fn create_pinned>( @@ -471,15 +465,12 @@ impl MapData { }) { Ok(fd) => { let fd = MapFd(fd); - Ok(Self { - obj, - fd, - pinned: false, - }) + Ok(Self { obj, fd }) } Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; - map.pin(name, path).map_err(|error| MapError::PinError { + let path = path.join(name); + map.pin(&path).map_err(|error| MapError::PinError { name: Some(name.into()), error, })?; @@ -489,7 +480,7 @@ impl MapData { } pub(crate) fn finalize(&mut self) -> Result<(), MapError> { - let Self { obj, fd, pinned: _ } = self; + let Self { obj, fd } = self; if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss { bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0) .map_err(|(_, io_error)| SyscallError { @@ -534,7 +525,6 @@ impl MapData { Ok(Self { obj: parse_map_info(info, PinningType::ByName), fd, - pinned: true, }) } @@ -550,44 +540,59 @@ impl MapData { Ok(Self { obj: parse_map_info(info, PinningType::None), fd, - pinned: false, }) } - pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { + /// Allows the map to be pinned to the provided path. + /// + /// Any directories in the the path provided should have been created by the caller. + /// The path must be on a BPF filesystem. + /// + /// # Errors + /// + /// Returns a [`PinError::SyscallError`] if the underlying syscall fails. + /// This may also happen if the path already exists, in which case the wrapped + /// [`std::io::Error`] kind will be [`std::io::ErrorKind::AlreadyExists`]. + /// Returns a [`PinError::InvalidPinPath`] if the path provided cannot be + /// converted to a [`CString`]. + /// + /// # Example + /// + /// ```no_run + /// # let mut bpf = aya::Bpf::load(&[])?; + /// # use aya::maps::MapData; + /// + /// let mut map = MapData::from_pin("/sys/fs/bpf/my_map")?; + /// map.pin("/sys/fs/bpf/my_map2")?; + /// + /// # Ok::<(), Box>(()) + /// ``` + pub fn pin>(&mut self, path: P) -> Result<(), PinError> { use std::os::unix::ffi::OsStrExt as _; - let Self { fd, pinned, obj: _ } = self; - if *pinned { - return Err(PinError::AlreadyPinned { name: name.into() }); - } - let path = path.as_ref().join(name); - let path_string = CString::new(path.as_os_str().as_bytes()) - .map_err(|error| PinError::InvalidPinPath { path, error })?; + let Self { fd, obj: _ } = self; + let path = path.as_ref(); + let path_string = CString::new(path.as_os_str().as_bytes()).map_err(|error| { + PinError::InvalidPinPath { + path: path.to_path_buf(), + error, + } + })?; bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, })?; - *pinned = true; Ok(()) } /// Returns the file descriptor of the map. pub fn fd(&self) -> &MapFd { - let Self { - obj: _, - fd, - pinned: _, - } = self; + let Self { obj: _, fd } = self; fd } pub(crate) fn obj(&self) -> &obj::Map { - let Self { - obj, - fd: _, - pinned: _, - } = self; + let Self { obj, fd: _ } = self; obj } } @@ -825,7 +830,6 @@ mod tests { Ok(MapData { obj: _, fd, - pinned: false }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) ); } diff --git a/aya/src/pin.rs b/aya/src/pin.rs index 743df95fc..43e197ff3 100644 --- a/aya/src/pin.rs +++ b/aya/src/pin.rs @@ -6,12 +6,6 @@ use thiserror::Error; /// An error ocurred working with a pinned BPF object. #[derive(Error, Debug)] pub enum PinError { - /// The object has already been pinned. - #[error("the BPF object `{name}` has already been pinned")] - AlreadyPinned { - /// Object name. - name: String, - }, /// The object FD is not known by Aya. #[error("the BPF object `{name}`'s FD is not known")] NoFd { diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 3f6dfad6d..1cf6eb5c7 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -1218,12 +1218,12 @@ pub fn aya::maps::lpm_trie::LpmTrie::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::from(t: T) -> T pub struct aya::maps::MapData -pub aya::maps::MapData::pinned: bool impl aya::maps::MapData pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option>) -> core::result::Result pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result +pub fn aya::maps::MapData::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::fmt::Debug for aya::maps::MapData pub fn aya::maps::MapData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::MapData @@ -1738,8 +1738,6 @@ pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData pub mod aya::pin pub enum aya::pin::PinError -pub aya::pin::PinError::AlreadyPinned -pub aya::pin::PinError::AlreadyPinned::name: alloc::string::String pub aya::pin::PinError::InvalidPinPath pub aya::pin::PinError::InvalidPinPath::error: alloc::ffi::c_str::NulError pub aya::pin::PinError::InvalidPinPath::path: std::path::PathBuf