Browse Source

Merge pull request #783 from astoycos/map_pin2

aya: Implement dedicated map pinning
Andrew Stoycos 1 year ago
parent
commit
ef27bce619

+ 31 - 7
aya/src/bpf.rs

@@ -398,7 +398,7 @@ impl<'a> BpfLoader<'a> {
             if let Some(btf) = obj.fixup_and_sanitize_btf(features)? {
                 match load_btf(btf.to_bytes(), *verifier_log_level) {
                     Ok(btf_fd) => Some(Arc::new(btf_fd)),
-                    // Only report an error here if the BTF is truely needed, otherwise proceed without.
+                    // Only report an error here if the BTF is truly needed, otherwise proceed without.
                     Err(err) => {
                         for program in obj.programs.values() {
                             match program.section {
@@ -492,8 +492,13 @@ impl<'a> BpfLoader<'a> {
             let mut map = match obj.pinning() {
                 PinningType::None => MapData::create(obj, &name, btf_fd)?,
                 PinningType::ByName => {
-                    let path = map_pin_path.as_ref().ok_or(BpfError::NoPinPath)?;
-                    MapData::create_pinned(path, obj, &name, btf_fd)?
+                    // pin maps in /sys/fs/bpf by default to align with libbpf
+                    // behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161.
+                    let path = map_pin_path
+                        .as_deref()
+                        .unwrap_or_else(|| Path::new("/sys/fs/bpf"));
+
+                    MapData::create_pinned_by_name(path, obj, &name, btf_fd)?
                 }
             };
             map.finalize()?;
@@ -856,6 +861,29 @@ impl Bpf {
         self.maps.iter().map(|(name, map)| (name.as_str(), map))
     }
 
+    /// A mutable iterator over all the maps.
+    ///
+    /// # Examples
+    /// ```no_run
+    /// # use std::path::Path;
+    /// # #[derive(thiserror::Error, Debug)]
+    /// # enum Error {
+    /// #     #[error(transparent)]
+    /// #     Bpf(#[from] aya::BpfError),
+    /// #     #[error(transparent)]
+    /// #     Pin(#[from] aya::pin::PinError)
+    /// # }
+    /// # let mut bpf = aya::Bpf::load(&[])?;
+    /// # let pin_path = Path::new("/tmp/pin_path");
+    /// for (_, map) in bpf.maps_mut() {
+    ///     map.pin(pin_path)?;
+    /// }
+    /// # Ok::<(), Error>(())
+    /// ```
+    pub fn maps_mut(&mut self) -> impl Iterator<Item = (&str, &mut Map)> {
+        self.maps.iter_mut().map(|(name, map)| (name.as_str(), map))
+    }
+
     /// Returns a reference to the program with the given name.
     ///
     /// You can use this to inspect a program and its properties. To load and attach a program, use
@@ -951,10 +979,6 @@ pub enum BpfError {
         error: io::Error,
     },
 
-    /// Pinning requested but no path provided
-    #[error("pinning requested but no path provided")]
-    NoPinPath,
-
     /// Unexpected pinning type
     #[error("unexpected pinning type {name}")]
     UnexpectedPinningType {

+ 1 - 1
aya/src/maps/array/array.rs

@@ -31,7 +31,7 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_ARRAY")]
 pub struct Array<T, V: Pod> {
-    inner: T,
+    pub(crate) inner: T,
     _v: PhantomData<V>,
 }
 

+ 1 - 1
aya/src/maps/array/per_cpu_array.rs

@@ -50,7 +50,7 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_PERCPU_ARRAY")]
 pub struct PerCpuArray<T, V: Pod> {
-    inner: T,
+    pub(crate) inner: T,
     _v: PhantomData<V>,
 }
 

+ 1 - 1
aya/src/maps/array/program_array.rs

@@ -48,7 +48,7 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
 pub struct ProgramArray<T> {
-    inner: T,
+    pub(crate) inner: T,
 }
 
 impl<T: Borrow<MapData>> ProgramArray<T> {

+ 1 - 1
aya/src/maps/bloom_filter.rs

@@ -36,7 +36,7 @@ use crate::{
 #[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")]
 #[derive(Debug)]
 pub struct BloomFilter<T, V: Pod> {
-    inner: T,
+    pub(crate) inner: T,
     _v: PhantomData<V>,
 }
 

+ 1 - 1
aya/src/maps/hash_map/hash_map.rs

@@ -34,7 +34,7 @@ use crate::{
 #[doc(alias = "BPF_MAP_TYPE_LRU_HASH")]
 #[derive(Debug)]
 pub struct HashMap<T, K, V> {
-    inner: T,
+    pub(crate) inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
 }

+ 1 - 1
aya/src/maps/hash_map/per_cpu_hash_map.rs

@@ -43,7 +43,7 @@ use crate::{
 #[doc(alias = "BPF_MAP_TYPE_LRU_PERCPU_HASH")]
 #[doc(alias = "BPF_MAP_TYPE_PERCPU_HASH")]
 pub struct PerCpuHashMap<T, K: Pod, V: Pod> {
-    inner: T,
+    pub(crate) inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
 }

+ 1 - 1
aya/src/maps/lpm_trie.rs

@@ -48,7 +48,7 @@ use crate::{
 #[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")]
 #[derive(Debug)]
 pub struct LpmTrie<T, K, V> {
-    inner: T,
+    pub(crate) inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
 }

+ 85 - 4
aya/src/maps/mod.rs

@@ -48,6 +48,7 @@
 //! versa. Because of that, all map values must be plain old data and therefore
 //! implement the [Pod] trait.
 use std::{
+    borrow::BorrowMut,
     ffi::CString,
     fmt, io,
     marker::PhantomData,
@@ -170,8 +171,8 @@ pub enum MapError {
     #[error(transparent)]
     SyscallError(#[from] SyscallError),
 
-    /// Could not pin map by name
-    #[error("map `{name:?}` requested pinning by name. pinning failed")]
+    /// Could not pin map
+    #[error("map `{name:?}` requested pinning. pinning failed")]
     PinError {
         /// The map name
         name: Option<String>,
@@ -308,8 +309,89 @@ impl Map {
             Self::Unsupported(map) => map.obj.map_type(),
         }
     }
+
+    /// Pins the map to a BPF filesystem.
+    ///
+    /// When a map is pinned it will remain loaded until the corresponding file
+    /// is deleted. All parent directories in the given `path` must already exist.
+    pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError> {
+        match self {
+            Self::Array(map) => map.pin(path),
+            Self::PerCpuArray(map) => map.pin(path),
+            Self::ProgramArray(map) => map.pin(path),
+            Self::HashMap(map) => map.pin(path),
+            Self::LruHashMap(map) => map.pin(path),
+            Self::PerCpuHashMap(map) => map.pin(path),
+            Self::PerCpuLruHashMap(map) => map.pin(path),
+            Self::PerfEventArray(map) => map.pin(path),
+            Self::SockHash(map) => map.pin(path),
+            Self::SockMap(map) => map.pin(path),
+            Self::BloomFilter(map) => map.pin(path),
+            Self::LpmTrie(map) => map.pin(path),
+            Self::Stack(map) => map.pin(path),
+            Self::StackTraceMap(map) => map.pin(path),
+            Self::Queue(map) => map.pin(path),
+            Self::CpuMap(map) => map.pin(path),
+            Self::DevMap(map) => map.pin(path),
+            Self::DevMapHash(map) => map.pin(path),
+            Self::XskMap(map) => map.pin(path),
+            Self::Unsupported(map) => map.pin(path),
+        }
+    }
+}
+
+// Implements map pinning for different map implementations
+// TODO add support for PerfEventArrays and AsyncPerfEventArrays
+macro_rules! impl_map_pin {
+    ($ty_param:tt {
+        $($ty:ident),+ $(,)?
+    }) => {
+        $(impl_map_pin!(<$ty_param> $ty);)+
+    };
+    (
+      <($($ty_param:ident),*)>
+      $ty:ident
+    ) => {
+            impl<T: BorrowMut<MapData>, $($ty_param: Pod),*> $ty<T, $($ty_param),*>
+            {
+                    /// Pins the map to a BPF filesystem.
+                    ///
+                    /// When a map is pinned it will remain loaded until the corresponding file
+                    /// is deleted. All parent directories in the given `path` must already exist.
+                    pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError> {
+                        let data = self.inner.borrow_mut();
+                        data.pin(path)
+                    }
+            }
+
+    };
 }
 
+impl_map_pin!(() {
+    ProgramArray,
+    SockMap,
+    StackTraceMap,
+    CpuMap,
+    DevMap,
+    DevMapHash,
+    XskMap,
+});
+
+impl_map_pin!((V) {
+    Array,
+    PerCpuArray,
+    SockHash,
+    BloomFilter,
+    Queue,
+    Stack,
+});
+
+impl_map_pin!((K, V) {
+    HashMap,
+    PerCpuHashMap,
+    LpmTrie,
+});
+
 // Implements TryFrom<Map> for different map implementations. Different map implementations can be
 // constructed from different variants of the map enum. Also, the implementation may have type
 // parameters (which we assume all have the bound `Pod` and nothing else).
@@ -461,7 +543,7 @@ impl MapData {
         Ok(Self { obj, fd })
     }
 
-    pub(crate) fn create_pinned<P: AsRef<Path>>(
+    pub(crate) fn create_pinned_by_name<P: AsRef<Path>>(
         path: P,
         obj: obj::Map,
         name: &str,
@@ -490,7 +572,6 @@ impl MapData {
             }
             Err(_) => {
                 let mut map = Self::create(obj, name, btf_fd)?;
-                let path = path.join(name);
                 map.pin(&path).map_err(|error| MapError::PinError {
                     name: Some(name.into()),
                     error,

+ 1 - 1
aya/src/maps/queue.rs

@@ -30,7 +30,7 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_QUEUE")]
 pub struct Queue<T, V: Pod> {
-    inner: T,
+    pub(crate) inner: T,
     _v: PhantomData<V>,
 }
 

+ 1 - 1
aya/src/maps/sock/sock_hash.rs

@@ -65,7 +65,7 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
 pub struct SockHash<T, K> {
-    inner: T,
+    pub(crate) inner: T,
     _k: PhantomData<K>,
 }
 

+ 1 - 1
aya/src/maps/stack.rs

@@ -30,7 +30,7 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_STACK")]
 pub struct Stack<T, V: Pod> {
-    inner: T,
+    pub(crate) inner: T,
     _v: PhantomData<V>,
 }
 

+ 1 - 1
aya/src/maps/stack_trace.rs

@@ -67,7 +67,7 @@ use crate::{
 #[derive(Debug)]
 #[doc(alias = "BPF_MAP_TYPE_STACK_TRACE")]
 pub struct StackTraceMap<T> {
-    inner: T,
+    pub(crate) inner: T,
     max_stack_depth: usize,
 }
 

+ 1 - 1
aya/src/maps/xdp/cpu_map.rs

@@ -50,7 +50,7 @@ use crate::{
 /// Kernel documentation: <https://docs.kernel.org/next/bpf/map_cpumap.html>
 #[doc(alias = "BPF_MAP_TYPE_CPUMAP")]
 pub struct CpuMap<T> {
-    inner: T,
+    pub(crate) inner: T,
 }
 
 impl<T: Borrow<MapData>> CpuMap<T> {

+ 1 - 1
aya/src/maps/xdp/dev_map.rs

@@ -42,7 +42,7 @@ use crate::{
 /// Kernel documentation: <https://docs.kernel.org/next/bpf/map_devmap.html>
 #[doc(alias = "BPF_MAP_TYPE_DEVMAP")]
 pub struct DevMap<T> {
-    inner: T,
+    pub(crate) inner: T,
 }
 
 impl<T: Borrow<MapData>> DevMap<T> {

+ 1 - 1
aya/src/maps/xdp/dev_map_hash.rs

@@ -42,7 +42,7 @@ use crate::{
 /// Kernel documentation: <https://docs.kernel.org/next/bpf/map_devmap.html>
 #[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")]
 pub struct DevMapHash<T> {
-    inner: T,
+    pub(crate) inner: T,
 }
 
 impl<T: Borrow<MapData>> DevMapHash<T> {

+ 1 - 1
aya/src/maps/xdp/xsk_map.rs

@@ -36,7 +36,7 @@ use crate::{
 /// Kernel documentation: <https://docs.kernel.org/next/bpf/map_xskmap.html>
 #[doc(alias = "BPF_MAP_TYPE_XSKMAP")]
 pub struct XskMap<T> {
-    inner: T,
+    pub(crate) inner: T,
 }
 
 impl<T: Borrow<MapData>> XskMap<T> {

+ 11 - 0
test/integration-test/bpf/multimap-btf.bpf.c

@@ -17,13 +17,24 @@ struct {
   __uint(max_entries, 1);
 } map_2 SEC(".maps");
 
+struct {
+  __uint(type, BPF_MAP_TYPE_ARRAY);
+  __type(key, __u32);
+  __type(value, __u64);
+  __uint(max_entries, 1);
+  __uint(pinning, LIBBPF_PIN_BY_NAME);
+} map_pin_by_name SEC(".maps");
+
 SEC("uprobe")
 int bpf_prog(void *ctx) {
   __u32 key = 0;
   __u64 twenty_four = 24;
   __u64 forty_two = 42;
+  __u64 forty_four = 44;
+
   bpf_map_update_elem(&map_1, &key, &twenty_four, BPF_ANY);
   bpf_map_update_elem(&map_2, &key, &forty_two, BPF_ANY);
+  bpf_map_update_elem(&map_pin_by_name, &key, &forty_four, BPF_ANY);
   return 0;
 }
 

+ 70 - 0
test/integration-test/src/tests/load.rs

@@ -1,5 +1,7 @@
 use std::{
     convert::TryInto as _,
+    fs::remove_file,
+    path::Path,
     thread,
     time::{Duration, SystemTime},
 };
@@ -40,6 +42,8 @@ fn multiple_btf_maps() {
 
     let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap();
     let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap();
+    let map_pin_by_name: Array<_, u64> =
+        bpf.take_map("map_pin_by_name").unwrap().try_into().unwrap();
 
     let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap();
     prog.load().unwrap();
@@ -51,9 +55,75 @@ fn multiple_btf_maps() {
     let key = 0;
     let val_1 = map_1.get(&key, 0).unwrap();
     let val_2 = map_2.get(&key, 0).unwrap();
+    let val_3 = map_pin_by_name.get(&key, 0).unwrap();
 
     assert_eq!(val_1, 24);
     assert_eq!(val_2, 42);
+    assert_eq!(val_3, 44);
+    let map_pin = Path::new("/sys/fs/bpf/map_pin_by_name");
+    assert!(&map_pin.exists());
+
+    remove_file(map_pin).unwrap();
+}
+
+#[test]
+fn pin_lifecycle_multiple_btf_maps() {
+    let mut bpf = Bpf::load(crate::MULTIMAP_BTF).unwrap();
+
+    // "map_pin_by_name" should already be pinned, unpin and pin again later
+    let map_pin_by_name_path = Path::new("/sys/fs/bpf/map_pin_by_name");
+
+    assert!(map_pin_by_name_path.exists());
+    remove_file(map_pin_by_name_path).unwrap();
+
+    // pin and unpin all maps before casting to explicit types
+    for (i, (name, map)) in bpf.maps_mut().enumerate() {
+        // Don't pin system maps or the map that's already pinned by name.
+        if name.contains(".rodata") || name.contains(".bss") {
+            continue;
+        }
+        let map_pin_path = &Path::new("/sys/fs/bpf/").join(i.to_string());
+
+        map.pin(map_pin_path).unwrap();
+
+        assert!(map_pin_path.exists());
+        remove_file(map_pin_path).unwrap();
+    }
+
+    let mut map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap();
+    let mut map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap();
+    let mut map_pin_by_name: Array<_, u64> =
+        bpf.take_map("map_pin_by_name").unwrap().try_into().unwrap();
+
+    let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap();
+    prog.load().unwrap();
+    prog.attach(Some("trigger_bpf_program"), 0, "/proc/self/exe", None)
+        .unwrap();
+
+    trigger_bpf_program();
+
+    let key = 0;
+    let val_1 = map_1.get(&key, 0).unwrap();
+    let val_2 = map_2.get(&key, 0).unwrap();
+    let val_3 = map_pin_by_name.get(&key, 0).unwrap();
+
+    assert_eq!(val_1, 24);
+    assert_eq!(val_2, 42);
+    assert_eq!(val_3, 44);
+
+    let map_1_pin_path = Path::new("/sys/fs/bpf/map_1");
+    let map_2_pin_path = Path::new("/sys/fs/bpf/map_2");
+
+    map_1.pin(map_1_pin_path).unwrap();
+    map_2.pin(map_2_pin_path).unwrap();
+    map_pin_by_name.pin(map_pin_by_name_path).unwrap();
+    assert!(map_1_pin_path.exists());
+    assert!(map_2_pin_path.exists());
+    assert!(map_pin_by_name_path.exists());
+
+    remove_file(map_1_pin_path).unwrap();
+    remove_file(map_2_pin_path).unwrap();
+    remove_file(map_pin_by_name_path).unwrap();
 }
 
 #[no_mangle]

+ 14 - 10
test/integration-test/src/tests/rbpf.rs

@@ -34,7 +34,7 @@ fn run_with_rbpf() {
     assert_eq!(vm.execute_program().unwrap(), XDP_PASS);
 }
 
-static mut MULTIMAP_MAPS: [*mut Vec<u64>; 2] = [null_mut(), null_mut()];
+static mut MULTIMAP_MAPS: [*mut Vec<u64>; 3] = [null_mut(); 3];
 
 #[test]
 fn use_map_with_rbpf() {
@@ -47,11 +47,11 @@ fn use_map_with_rbpf() {
     );
 
     // Initialize maps:
-    // - fd: 0xCAFE00 or 0xCAFE01 (the 0xCAFE00 part is used to distinguish fds from indices),
+    // - fd: Bitwise OR of the map_id with 0xCAFE00 (used to distinguish fds from indices),
     // - Note that rbpf does not convert fds into real pointers,
     //   so we keeps the pointers to our maps in MULTIMAP_MAPS, to be used in helpers.
     let mut maps = HashMap::new();
-    let mut map_instances = vec![vec![0u64], vec![0u64]];
+    let mut map_instances = vec![vec![0u64], vec![0u64], vec![0u64]];
     for (name, map) in object.maps.iter() {
         assert_eq!(map.key_size(), size_of::<u32>() as u32);
         assert_eq!(map.value_size(), size_of::<u64>() as u32);
@@ -60,8 +60,14 @@ fn use_map_with_rbpf() {
             aya_obj::generated::bpf_map_type::BPF_MAP_TYPE_ARRAY as u32
         );
 
-        let map_id = if name == "map_1" { 0 } else { 1 };
-        let fd = map_id as std::os::fd::RawFd | 0xCAFE00;
+        let map_id = match name.as_str() {
+            "map_1" => 0,
+            "map_2" => 1,
+            "map_pin_by_name" => 2,
+            n => panic!("Unexpected map: {n}"),
+        };
+
+        let fd = map_id as i32 | 0xCAFE00;
         maps.insert(name.to_owned(), (fd, map.clone()));
 
         unsafe {
@@ -102,18 +108,16 @@ fn use_map_with_rbpf() {
         .expect("Helper failed");
     assert_eq!(vm.execute_program().unwrap(), 0);
 
-    assert_eq!(map_instances[0][0], 24);
-    assert_eq!(map_instances[1][0], 42);
+    assert_eq!(map_instances, [[24], [42], [44]]);
 
     unsafe {
-        MULTIMAP_MAPS[0] = null_mut();
-        MULTIMAP_MAPS[1] = null_mut();
+        MULTIMAP_MAPS.iter_mut().for_each(|v| *v = null_mut());
     }
 }
 
 #[track_caller]
 fn bpf_map_update_elem_multimap(map: u64, key: u64, value: u64, _: u64, _: u64) -> u64 {
-    assert_matches!(map, 0xCAFE00 | 0xCAFE01);
+    assert_matches!(map, 0xCAFE00 | 0xCAFE01 | 0xCAFE02);
     let key = *unsafe { (key as usize as *const u32).as_ref().unwrap() };
     let value = *unsafe { (value as usize as *const u64).as_ref().unwrap() };
     assert_eq!(key, 0);

+ 67 - 1
xtask/public-api/aya.txt

@@ -12,6 +12,8 @@ pub fn aya::maps::array::Array<T, V>::get(&self, index: &u32, flags: u64) -> cor
 pub fn aya::maps::array::Array<T, V>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<V, aya::maps::MapError>> + '_
 pub fn aya::maps::array::Array<T, V>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::array::Array<T, V>
+pub fn aya::maps::array::Array<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::array::Array<T, V>
 pub fn aya::maps::array::Array<T, V>::set(&mut self, index: u32, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V>
 pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
@@ -52,6 +54,8 @@ pub fn aya::maps::PerCpuArray<T, V>::get(&self, index: &u32, flags: u64) -> core
 pub fn aya::maps::PerCpuArray<T, V>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::maps::PerCpuValues<V>, aya::maps::MapError>> + '_
 pub fn aya::maps::PerCpuArray<T, V>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::PerCpuArray<T, V>
+pub fn aya::maps::PerCpuArray<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::PerCpuArray<T, V>
 pub fn aya::maps::PerCpuArray<T, V>::set(&mut self, index: u32, values: aya::maps::PerCpuValues<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V>
 pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
@@ -92,6 +96,8 @@ pub fn aya::maps::ProgramArray<T>::indices(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::ProgramArray<T>
 pub fn aya::maps::ProgramArray<T>::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::ProgramArray<T>::set(&mut self, index: u32, program: &aya::programs::ProgramFd, flags: u64) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::ProgramArray<T>
+pub fn aya::maps::ProgramArray<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::ProgramArray<aya::maps::MapData>
 pub type aya::maps::ProgramArray<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::ProgramArray<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -128,6 +134,8 @@ impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_
 pub fn aya::maps::bloom_filter::BloomFilter<T, V>::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
 pub fn aya::maps::bloom_filter::BloomFilter<T, V>::insert(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
+pub fn aya::maps::bloom_filter::BloomFilter<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>
 pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
 pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -169,6 +177,8 @@ pub fn aya::maps::hash_map::HashMap<T, K, V>::keys(&self) -> aya::maps::MapKeys<
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap<T, K, V>
 pub fn aya::maps::hash_map::HashMap<T, K, V>::insert(&mut self, key: impl core::borrow::Borrow<K>, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::hash_map::HashMap<T, K, V>::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap<T, K, V>
+pub fn aya::maps::hash_map::HashMap<T, K, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>
 pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError
 pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -212,6 +222,8 @@ pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::keys(&self) -> aya::maps::Ma
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap<T, K, V>
 pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::insert(&mut self, key: impl core::borrow::Borrow<K>, values: aya::maps::PerCpuValues<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap<T, K, V>
+pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>
 pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError
 pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -291,6 +303,8 @@ pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::keys(&self) -> aya::maps::MapKeys<
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie<T, K, V>
 pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::insert(&mut self, key: &aya::maps::lpm_trie::Key<K>, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::remove(&mut self, key: &aya::maps::lpm_trie::Key<K>) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie<T, K, V>
+pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>
 pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError
 pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -524,6 +538,8 @@ pub struct aya::maps::queue::Queue<T, V: aya::Pod>
 impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::queue::Queue<T, V>
 pub fn aya::maps::queue::Queue<T, V>::capacity(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::queue::Queue<T, V>
+pub fn aya::maps::queue::Queue<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::queue::Queue<T, V>
 pub fn aya::maps::queue::Queue<T, V>::pop(&mut self, flags: u64) -> core::result::Result<V, aya::maps::MapError>
 pub fn aya::maps::queue::Queue<T, V>::push(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V>
@@ -566,6 +582,8 @@ pub fn aya::maps::SockHash<T, K>::keys(&self) -> aya::maps::MapKeys<'_, K>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod> aya::maps::SockHash<T, K>
 pub fn aya::maps::SockHash<T, K>::insert<I: std::os::fd::raw::AsRawFd>(&mut self, key: impl core::borrow::Borrow<K>, value: I, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::SockHash<T, K>::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::SockHash<T, V>
+pub fn aya::maps::SockHash<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V>
 pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
 pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -606,6 +624,8 @@ pub fn aya::maps::SockMap<T>::indices(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::SockMap<T>
 pub fn aya::maps::SockMap<T>::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::SockMap<T>::set<I: std::os::fd::raw::AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::SockMap<T>
+pub fn aya::maps::SockMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::SockMap<aya::maps::MapData>
 pub type aya::maps::SockMap<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::SockMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -667,6 +687,8 @@ pub struct aya::maps::stack::Stack<T, V: aya::Pod>
 impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::stack::Stack<T, V>
 pub fn aya::maps::stack::Stack<T, V>::capacity(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::stack::Stack<T, V>
+pub fn aya::maps::stack::Stack<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::stack::Stack<T, V>
 pub fn aya::maps::stack::Stack<T, V>::pop(&mut self, flags: u64) -> core::result::Result<V, aya::maps::MapError>
 pub fn aya::maps::stack::Stack<T, V>::push(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V>
@@ -756,6 +778,8 @@ impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::stack_trace::StackT
 pub fn aya::maps::stack_trace::StackTraceMap<T>::get(&self, stack_id: &u32, flags: u64) -> core::result::Result<aya::maps::stack_trace::StackTrace, aya::maps::MapError>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::iter(&self) -> aya::maps::MapIter<'_, u32, aya::maps::stack_trace::StackTrace, Self>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::stack_ids(&self) -> aya::maps::MapKeys<'_, u32>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::stack_trace::StackTraceMap<T>
+pub fn aya::maps::stack_trace::StackTraceMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<aya::maps::MapData>
 pub type aya::maps::stack_trace::StackTraceMap<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::stack_trace::StackTraceMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -836,6 +860,8 @@ pub fn aya::maps::CpuMap<T>::get(&self, cpu_index: u32, flags: u64) -> core::res
 pub fn aya::maps::CpuMap<T>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<CpuMapValue, aya::maps::MapError>> + '_
 pub fn aya::maps::CpuMap<T>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::CpuMap<T>
+pub fn aya::maps::CpuMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::CpuMap<T>
 pub fn aya::maps::CpuMap<T>::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::CpuMap<aya::maps::MapData>
 pub type aya::maps::CpuMap<aya::maps::MapData>::Error = aya::maps::MapError
@@ -873,6 +899,8 @@ pub fn aya::maps::DevMap<T>::get(&self, index: u32, flags: u64) -> core::result:
 pub fn aya::maps::DevMap<T>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<DevMapValue, aya::maps::MapError>> + '_
 pub fn aya::maps::DevMap<T>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMap<T>
+pub fn aya::maps::DevMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMap<T>
 pub fn aya::maps::DevMap<T>::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::DevMap<aya::maps::MapData>
 pub type aya::maps::DevMap<aya::maps::MapData>::Error = aya::maps::MapError
@@ -912,6 +940,8 @@ pub fn aya::maps::DevMapHash<T>::keys(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMapHash<T>
 pub fn aya::maps::DevMapHash<T>::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError>
 pub fn aya::maps::DevMapHash<T>::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMapHash<T>
+pub fn aya::maps::DevMapHash<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::DevMapHash<aya::maps::MapData>
 pub type aya::maps::DevMapHash<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::DevMapHash<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -946,6 +976,8 @@ pub struct aya::maps::xdp::XskMap<T>
 impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::XskMap<T>
 pub fn aya::maps::XskMap<T>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T>
+pub fn aya::maps::XskMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T>
 pub fn aya::maps::XskMap<T>::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::XskMap<aya::maps::MapData>
 pub type aya::maps::XskMap<aya::maps::MapData>::Error = aya::maps::MapError
@@ -998,6 +1030,8 @@ pub aya::maps::Map::Stack(aya::maps::MapData)
 pub aya::maps::Map::StackTraceMap(aya::maps::MapData)
 pub aya::maps::Map::Unsupported(aya::maps::MapData)
 pub aya::maps::Map::XskMap(aya::maps::MapData)
+impl aya::maps::Map
+pub fn aya::maps::Map::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::CpuMap<aya::maps::MapData>
 pub type aya::maps::CpuMap<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::CpuMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1252,6 +1286,8 @@ pub fn aya::maps::array::Array<T, V>::get(&self, index: &u32, flags: u64) -> cor
 pub fn aya::maps::array::Array<T, V>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<V, aya::maps::MapError>> + '_
 pub fn aya::maps::array::Array<T, V>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::array::Array<T, V>
+pub fn aya::maps::array::Array<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::array::Array<T, V>
 pub fn aya::maps::array::Array<T, V>::set(&mut self, index: u32, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::array::Array<&'a aya::maps::MapData, V>
 pub type aya::maps::array::Array<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
@@ -1324,6 +1360,8 @@ impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_
 pub fn aya::maps::bloom_filter::BloomFilter<T, V>::contains(&self, value: &V, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
 pub fn aya::maps::bloom_filter::BloomFilter<T, V>::insert(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::bloom_filter::BloomFilter<T, V>
+pub fn aya::maps::bloom_filter::BloomFilter<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>
 pub type aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
 pub fn aya::maps::bloom_filter::BloomFilter<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1362,6 +1400,8 @@ pub fn aya::maps::CpuMap<T>::get(&self, cpu_index: u32, flags: u64) -> core::res
 pub fn aya::maps::CpuMap<T>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<CpuMapValue, aya::maps::MapError>> + '_
 pub fn aya::maps::CpuMap<T>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::CpuMap<T>
+pub fn aya::maps::CpuMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::CpuMap<T>
 pub fn aya::maps::CpuMap<T>::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::CpuMap<aya::maps::MapData>
 pub type aya::maps::CpuMap<aya::maps::MapData>::Error = aya::maps::MapError
@@ -1399,6 +1439,8 @@ pub fn aya::maps::DevMap<T>::get(&self, index: u32, flags: u64) -> core::result:
 pub fn aya::maps::DevMap<T>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<DevMapValue, aya::maps::MapError>> + '_
 pub fn aya::maps::DevMap<T>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMap<T>
+pub fn aya::maps::DevMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMap<T>
 pub fn aya::maps::DevMap<T>::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::DevMap<aya::maps::MapData>
 pub type aya::maps::DevMap<aya::maps::MapData>::Error = aya::maps::MapError
@@ -1438,6 +1480,8 @@ pub fn aya::maps::DevMapHash<T>::keys(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMapHash<T>
 pub fn aya::maps::DevMapHash<T>::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError>
 pub fn aya::maps::DevMapHash<T>::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::DevMapHash<T>
+pub fn aya::maps::DevMapHash<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::DevMapHash<aya::maps::MapData>
 pub type aya::maps::DevMapHash<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::DevMapHash<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1476,6 +1520,8 @@ pub fn aya::maps::hash_map::HashMap<T, K, V>::keys(&self) -> aya::maps::MapKeys<
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap<T, K, V>
 pub fn aya::maps::hash_map::HashMap<T, K, V>::insert(&mut self, key: impl core::borrow::Borrow<K>, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::hash_map::HashMap<T, K, V>::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap<T, K, V>
+pub fn aya::maps::hash_map::HashMap<T, K, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>
 pub type aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError
 pub fn aya::maps::hash_map::HashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1519,6 +1565,8 @@ pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::keys(&self) -> aya::maps::MapKeys<
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie<T, K, V>
 pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::insert(&mut self, key: &aya::maps::lpm_trie::Key<K>, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::remove(&mut self, key: &aya::maps::lpm_trie::Key<K>) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::lpm_trie::LpmTrie<T, K, V>
+pub fn aya::maps::lpm_trie::LpmTrie<T, K, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>
 pub type aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError
 pub fn aya::maps::lpm_trie::LpmTrie<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1674,6 +1722,8 @@ pub fn aya::maps::PerCpuArray<T, V>::get(&self, index: &u32, flags: u64) -> core
 pub fn aya::maps::PerCpuArray<T, V>::iter(&self) -> impl core::iter::traits::iterator::Iterator<Item = core::result::Result<aya::maps::PerCpuValues<V>, aya::maps::MapError>> + '_
 pub fn aya::maps::PerCpuArray<T, V>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::PerCpuArray<T, V>
+pub fn aya::maps::PerCpuArray<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::PerCpuArray<T, V>
 pub fn aya::maps::PerCpuArray<T, V>::set(&mut self, index: u32, values: aya::maps::PerCpuValues<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::PerCpuArray<&'a aya::maps::MapData, V>
 pub type aya::maps::PerCpuArray<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
@@ -1716,6 +1766,8 @@ pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::keys(&self) -> aya::maps::Ma
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap<T, K, V>
 pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::insert(&mut self, key: impl core::borrow::Borrow<K>, values: aya::maps::PerCpuValues<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::PerCpuHashMap<T, K, V>
+pub fn aya::maps::hash_map::PerCpuHashMap<T, K, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, K: aya::Pod, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>
 pub type aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::Error = aya::maps::MapError
 pub fn aya::maps::hash_map::PerCpuHashMap<&'a aya::maps::MapData, K, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1824,6 +1876,8 @@ pub fn aya::maps::ProgramArray<T>::indices(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::ProgramArray<T>
 pub fn aya::maps::ProgramArray<T>::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::ProgramArray<T>::set(&mut self, index: u32, program: &aya::programs::ProgramFd, flags: u64) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::ProgramArray<T>
+pub fn aya::maps::ProgramArray<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::ProgramArray<aya::maps::MapData>
 pub type aya::maps::ProgramArray<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::ProgramArray<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1858,6 +1912,8 @@ pub struct aya::maps::Queue<T, V: aya::Pod>
 impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::queue::Queue<T, V>
 pub fn aya::maps::queue::Queue<T, V>::capacity(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::queue::Queue<T, V>
+pub fn aya::maps::queue::Queue<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::queue::Queue<T, V>
 pub fn aya::maps::queue::Queue<T, V>::pop(&mut self, flags: u64) -> core::result::Result<V, aya::maps::MapError>
 pub fn aya::maps::queue::Queue<T, V>::push(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::queue::Queue<&'a aya::maps::MapData, V>
@@ -1899,6 +1955,8 @@ pub fn aya::maps::SockHash<T, K>::keys(&self) -> aya::maps::MapKeys<'_, K>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, K: aya::Pod> aya::maps::SockHash<T, K>
 pub fn aya::maps::SockHash<T, K>::insert<I: std::os::fd::raw::AsRawFd>(&mut self, key: impl core::borrow::Borrow<K>, value: I, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::SockHash<T, K>::remove(&mut self, key: &K) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::SockHash<T, V>
+pub fn aya::maps::SockHash<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockHash<&'a aya::maps::MapData, V>
 pub type aya::maps::SockHash<&'a aya::maps::MapData, V>::Error = aya::maps::MapError
 pub fn aya::maps::SockHash<&'a aya::maps::MapData, V>::try_from(map: &'a aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1939,6 +1997,8 @@ pub fn aya::maps::SockMap<T>::indices(&self) -> aya::maps::MapKeys<'_, u32>
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::SockMap<T>
 pub fn aya::maps::SockMap<T>::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError>
 pub fn aya::maps::SockMap<T>::set<I: std::os::fd::raw::AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> core::result::Result<(), aya::maps::MapError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::SockMap<T>
+pub fn aya::maps::SockMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::SockMap<aya::maps::MapData>
 pub type aya::maps::SockMap<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::SockMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -1973,6 +2033,8 @@ pub struct aya::maps::Stack<T, V: aya::Pod>
 impl<T: core::borrow::Borrow<aya::maps::MapData>, V: aya::Pod> aya::maps::stack::Stack<T, V>
 pub fn aya::maps::stack::Stack<T, V>::capacity(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::stack::Stack<T, V>
+pub fn aya::maps::stack::Stack<T, V>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>, V: aya::Pod> aya::maps::stack::Stack<T, V>
 pub fn aya::maps::stack::Stack<T, V>::pop(&mut self, flags: u64) -> core::result::Result<V, aya::maps::MapError>
 pub fn aya::maps::stack::Stack<T, V>::push(&mut self, value: impl core::borrow::Borrow<V>, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl<'a, V: aya::Pod> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack::Stack<&'a aya::maps::MapData, V>
@@ -2010,6 +2072,8 @@ impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::stack_trace::StackT
 pub fn aya::maps::stack_trace::StackTraceMap<T>::get(&self, stack_id: &u32, flags: u64) -> core::result::Result<aya::maps::stack_trace::StackTrace, aya::maps::MapError>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::iter(&self) -> aya::maps::MapIter<'_, u32, aya::maps::stack_trace::StackTrace, Self>
 pub fn aya::maps::stack_trace::StackTraceMap<T>::stack_ids(&self) -> aya::maps::MapKeys<'_, u32>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::stack_trace::StackTraceMap<T>
+pub fn aya::maps::stack_trace::StackTraceMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<aya::maps::MapData>
 pub type aya::maps::stack_trace::StackTraceMap<aya::maps::MapData>::Error = aya::maps::MapError
 pub fn aya::maps::stack_trace::StackTraceMap<aya::maps::MapData>::try_from(map: aya::maps::Map) -> core::result::Result<Self, Self::Error>
@@ -2053,6 +2117,8 @@ pub struct aya::maps::XskMap<T>
 impl<T: core::borrow::Borrow<aya::maps::MapData>> aya::maps::XskMap<T>
 pub fn aya::maps::XskMap<T>::len(&self) -> u32
 impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T>
+pub fn aya::maps::XskMap<T>::pin<P: core::convert::AsRef<std::path::Path>>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError>
+impl<T: core::borrow::BorrowMut<aya::maps::MapData>> aya::maps::XskMap<T>
 pub fn aya::maps::XskMap<T>::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError>
 impl core::convert::TryFrom<aya::maps::Map> for aya::maps::XskMap<aya::maps::MapData>
 pub type aya::maps::XskMap<aya::maps::MapData>::Error = aya::maps::MapError
@@ -7349,7 +7415,6 @@ pub aya::BpfError::FileError::error: std::io::error::Error
 pub aya::BpfError::FileError::path: std::path::PathBuf
 pub aya::BpfError::MapError(aya::maps::MapError)
 pub aya::BpfError::NoBTF
-pub aya::BpfError::NoPinPath
 pub aya::BpfError::ParseError(aya_obj::obj::ParseError)
 pub aya::BpfError::ProgramError(aya::programs::ProgramError)
 pub aya::BpfError::RelocationError(aya_obj::relocation::BpfRelocationError)
@@ -7403,6 +7468,7 @@ pub fn aya::Bpf::load_file<P: core::convert::AsRef<std::path::Path>>(path: P) ->
 pub fn aya::Bpf::map(&self, name: &str) -> core::option::Option<&aya::maps::Map>
 pub fn aya::Bpf::map_mut(&mut self, name: &str) -> core::option::Option<&mut aya::maps::Map>
 pub fn aya::Bpf::maps(&self) -> impl core::iter::traits::iterator::Iterator<Item = (&str, &aya::maps::Map)>
+pub fn aya::Bpf::maps_mut(&mut self) -> impl core::iter::traits::iterator::Iterator<Item = (&str, &mut aya::maps::Map)>
 pub fn aya::Bpf::program(&self, name: &str) -> core::option::Option<&aya::programs::Program>
 pub fn aya::Bpf::program_mut(&mut self, name: &str) -> core::option::Option<&mut aya::programs::Program>
 pub fn aya::Bpf::programs(&self) -> impl core::iter::traits::iterator::Iterator<Item = (&str, &aya::programs::Program)>