Browse Source

Core refactor of Map API

Build completing tests passing

Refactor the Map API to better align
with the aya programs API.  Specifically
remove all internal locking mechanisms
and custom Deref/DerefMut implementations.
They are replaced with a Map enum
and AsRef/AsMut implementations.

All Try_From implementations have been moved
to standardized enums, with a slightly
special one for PerfEventArray's.

Also cleanup/fix all associated tests and
documentation.

Signed-off-by: Andrew Stoycos <[email protected]>
Andrew Stoycos 2 years ago
parent
commit
1aefa2e5e6

+ 1 - 1
aya-log/src/lib.rs

@@ -90,7 +90,7 @@ impl BpfLogger {
         logger: T,
     ) -> Result<BpfLogger, Error> {
         let logger = Arc::new(logger);
-        let mut logs: AsyncPerfEventArray<_> = bpf.map_mut("AYA_LOGS")?.try_into()?;
+        let mut logs: AsyncPerfEventArray<_> = bpf.take_map("AYA_LOGS")?.try_into()?;
 
         for cpu_id in online_cpus().map_err(Error::InvalidOnlineCpu)? {
             let mut buf = logs.open(cpu_id, None)?;

+ 67 - 43
aya/src/bpf.rs

@@ -13,10 +13,10 @@ use thiserror::Error;
 
 use crate::{
     generated::{
-        bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY, AYA_PERF_EVENT_IOC_DISABLE,
-        AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF,
+        bpf_map_type::*, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE,
+        AYA_PERF_EVENT_IOC_SET_BPF,
     },
-    maps::{Map, MapError, MapLock, MapRef, MapRefMut},
+    maps::{Map, MapData, MapError},
     obj::{
         btf::{Btf, BtfError},
         MapKind, Object, ParseError, ProgramSection,
@@ -451,7 +451,7 @@ impl<'a> BpfLoader<'a> {
                     }
                 }
             }
-            let mut map = Map {
+            let mut map = MapData {
                 obj,
                 fd: None,
                 pinned: false,
@@ -638,14 +638,41 @@ impl<'a> BpfLoader<'a> {
                 (name, program)
             })
             .collect();
-        let maps = maps
-            .drain()
-            .map(|(name, map)| (name, MapLock::new(map)))
-            .collect();
-        Ok(Bpf { maps, programs })
+        let maps: Result<HashMap<String, Map>, BpfError> = maps.drain().map(parse_map).collect();
+
+        Ok(Bpf {
+            maps: maps?,
+            programs,
+        })
     }
 }
 
+fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> {
+    let name = data.0;
+    let map = data.1;
+    let map_type = map.map_type().map_err(BpfError::MapError)?;
+    let map = match map_type {
+        BPF_MAP_TYPE_ARRAY => Ok(Map::Array(map)),
+        BPF_MAP_TYPE_PERCPU_ARRAY => Ok(Map::PerCpuArray(map)),
+        BPF_MAP_TYPE_PROG_ARRAY => Ok(Map::ProgramArray(map)),
+        BPF_MAP_TYPE_HASH => Ok(Map::HashMap(map)),
+        BPF_MAP_TYPE_PERCPU_HASH => Ok(Map::PerCpuHashMap(map)),
+        BPF_MAP_TYPE_PERF_EVENT_ARRAY => Ok(Map::PerfEventArray(map)),
+        BPF_MAP_TYPE_SOCKHASH => Ok(Map::SockHash(map)),
+        BPF_MAP_TYPE_SOCKMAP => Ok(Map::SockMap(map)),
+        BPF_MAP_TYPE_BLOOM_FILTER => Ok(Map::BloomFilter(map)),
+        BPF_MAP_TYPE_LPM_TRIE => Ok(Map::LpmTrie(map)),
+        BPF_MAP_TYPE_STACK => Ok(Map::Stack(map)),
+        BPF_MAP_TYPE_STACK_TRACE => Ok(Map::StackTraceMap(map)),
+        BPF_MAP_TYPE_QUEUE => Ok(Map::Queue(map)),
+        m => Err(BpfError::MapError(MapError::InvalidMapType {
+            map_type: m as u32,
+        })),
+    }?;
+
+    Ok((name, map))
+}
+
 impl<'a> Default for BpfLoader<'a> {
     fn default() -> Self {
         BpfLoader::new()
@@ -655,7 +682,7 @@ impl<'a> Default for BpfLoader<'a> {
 /// The main entry point into the library, used to work with eBPF programs and maps.
 #[derive(Debug)]
 pub struct Bpf {
-    maps: HashMap<String, MapLock>,
+    maps: HashMap<String, Map>,
     programs: HashMap<String, Program>,
 }
 
@@ -717,19 +744,11 @@ impl Bpf {
     ///
     /// # Errors
     ///
-    /// Returns [`MapError::MapNotFound`] if the map does not exist. If the map is already borrowed
-    /// mutably with [map_mut](Self::map_mut) then [`MapError::BorrowError`] is returned.
-    pub fn map(&self, name: &str) -> Result<MapRef, MapError> {
-        self.maps
-            .get(name)
-            .ok_or_else(|| MapError::MapNotFound {
-                name: name.to_owned(),
-            })
-            .and_then(|lock| {
-                lock.try_read().map_err(|_| MapError::BorrowError {
-                    name: name.to_owned(),
-                })
-            })
+    /// Returns [`MapError::MapNotFound`] if the map does not exist.
+    pub fn map(&self, name: &str) -> Result<&Map, MapError> {
+        self.maps.get(name).ok_or_else(|| MapError::MapNotFound {
+            name: name.to_owned(),
+        })
     }
 
     /// Returns a mutable reference to the map with the given name.
@@ -742,19 +761,32 @@ impl Bpf {
     ///
     /// # Errors
     ///
-    /// Returns [`MapError::MapNotFound`] if the map does not exist. If the map is already borrowed
-    /// mutably with [map_mut](Self::map_mut) then [`MapError::BorrowError`] is returned.
-    pub fn map_mut(&self, name: &str) -> Result<MapRefMut, MapError> {
+    /// Returns [`MapError::MapNotFound`] if the map does not exist.
+    pub fn map_mut(&mut self, name: &str) -> Result<&mut Map, MapError> {
         self.maps
-            .get(name)
+            .get_mut(name)
             .ok_or_else(|| MapError::MapNotFound {
                 name: name.to_owned(),
             })
-            .and_then(|lock| {
-                lock.try_write().map_err(|_| MapError::BorrowError {
-                    name: name.to_owned(),
-                })
-            })
+    }
+
+    /// Returns a map with the given name.
+    ///
+    /// WARNING: This transfers ownership of the map to the user.
+    ///
+    /// The returned type is mostly opaque. In order to do anything useful with it you need to
+    /// convert it to a [typed map](crate::maps).
+    ///
+    /// For more details and examples on maps and their usage, see the [maps module
+    /// documentation][crate::maps].
+    ///
+    /// # Errors
+    ///
+    /// Returns [`MapError::MapNotFound`] if the map does not exist.
+    pub fn take_map(&mut self, name: &str) -> Result<Map, MapError> {
+        self.maps.remove(name).ok_or_else(|| MapError::MapNotFound {
+            name: name.to_owned(),
+        })
     }
 
     /// An iterator over all the maps.
@@ -764,22 +796,14 @@ impl Bpf {
     /// # let mut bpf = aya::Bpf::load(&[])?;
     /// for (name, map) in bpf.maps() {
     ///     println!(
-    ///         "found map `{}` of type `{:?}`",
+    ///         "found map `{}`",
     ///         name,
-    ///         map?.map_type().unwrap()
     ///     );
     /// }
     /// # Ok::<(), aya::BpfError>(())
     /// ```
-    pub fn maps(&self) -> impl Iterator<Item = (&str, Result<MapRef, MapError>)> {
-        let ret = self.maps.iter().map(|(name, lock)| {
-            (
-                name.as_str(),
-                lock.try_read()
-                    .map_err(|_| MapError::BorrowError { name: name.clone() }),
-            )
-        });
-        ret
+    pub fn maps(&self) -> impl Iterator<Item = (&str, Result<&Map, MapError>)> {
+        self.maps.iter().map(|(name, map)| (name.as_str(), Ok(map)))
     }
 
     /// Returns a reference to the program with the given name.

+ 22 - 49
aya/src/maps/array/array.rs

@@ -1,12 +1,11 @@
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
     mem,
-    ops::{Deref, DerefMut},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_ARRAY,
-    maps::{IterableMap, Map, MapError, MapRef, MapRefMut},
+    maps::{array, IterableMap, MapData, MapError},
     sys::{bpf_map_lookup_elem, bpf_map_update_elem},
     Pod,
 };
@@ -22,38 +21,35 @@ use crate::{
 ///
 /// # Examples
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::Array;
 ///
-/// let mut array = Array::try_from(bpf.map_mut("ARRAY")?)?;
+/// let mut array: Array<_, u32> = bpf.map_mut("ARRAY")?.try_into()?;
 /// array.set(1, 42, 0)?;
 /// assert_eq!(array.get(&1, 0)?, 42);
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_ARRAY")]
-pub struct Array<T: Deref<Target = Map>, V: Pod> {
+pub struct Array<T, V: Pod> {
     inner: T,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, V: Pod> Array<T, V> {
-    fn new(map: T) -> Result<Array<T, V>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_ARRAY as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>, V: Pod> Array<T, V> {
+    pub(crate) fn new(map: T) -> Result<Array<T, V>, MapError> {
+        let data = map.as_ref();
         let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
 
         let expected = mem::size_of::<V>();
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(Array {
             inner: map,
@@ -65,7 +61,7 @@ impl<T: Deref<Target = Map>, V: Pod> Array<T, V> {
     ///
     /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
     pub fn len(&self) -> u32 {
-        self.inner.obj.max_entries()
+        self.inner.as_ref().obj.max_entries()
     }
 
     /// Returns the value stored at the given index.
@@ -75,8 +71,9 @@ impl<T: Deref<Target = Map>, V: Pod> Array<T, V> {
     /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
     /// if `bpf_map_lookup_elem` fails.
     pub fn get(&self, index: &u32, flags: u64) -> Result<V, MapError> {
-        self.check_bounds(*index)?;
-        let fd = self.inner.fd_or_err()?;
+        let data = self.inner.as_ref();
+        array::check_bounds(data, *index)?;
+        let fd = data.fd_or_err()?;
 
         let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
@@ -92,18 +89,9 @@ impl<T: Deref<Target = Map>, V: Pod> Array<T, V> {
     pub fn iter(&self) -> impl Iterator<Item = Result<V, MapError>> + '_ {
         (0..self.len()).map(move |i| self.get(&i, 0))
     }
-
-    fn check_bounds(&self, index: u32) -> Result<(), MapError> {
-        let max_entries = self.inner.obj.max_entries();
-        if index >= self.inner.obj.max_entries() {
-            Err(MapError::OutOfBounds { index, max_entries })
-        } else {
-            Ok(())
-        }
-    }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Array<T, V> {
+impl<T: AsMut<MapData>, V: Pod> Array<T, V> {
     /// Sets the value of the element at the given index.
     ///
     /// # Errors
@@ -111,8 +99,9 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Array<T, V> {
     /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
     /// if `bpf_map_update_elem` fails.
     pub fn set(&mut self, index: u32, value: V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
-        self.check_bounds(index)?;
+        let data = self.inner.as_mut();
+        array::check_bounds(data, index)?;
+        let fd = data.fd_or_err()?;
         bpf_map_update_elem(fd, Some(&index), &value, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_update_elem".to_owned(),
@@ -123,28 +112,12 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Array<T, V> {
     }
 }
 
-impl<T: Deref<Target = Map>, V: Pod> IterableMap<u32, V> for Array<T, V> {
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>, V: Pod> IterableMap<u32, V> for Array<T, V> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, index: &u32) -> Result<V, MapError> {
         self.get(index, 0)
     }
 }
-
-impl<V: Pod> TryFrom<MapRef> for Array<MapRef, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<Array<MapRef, V>, MapError> {
-        Array::new(a)
-    }
-}
-
-impl<V: Pod> TryFrom<MapRefMut> for Array<MapRefMut, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<Array<MapRefMut, V>, MapError> {
-        Array::new(a)
-    }
-}

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

@@ -4,6 +4,17 @@ mod array;
 mod per_cpu_array;
 mod program_array;
 
-pub use array::Array;
+pub use array::*;
 pub use per_cpu_array::PerCpuArray;
 pub use program_array::ProgramArray;
+
+use crate::maps::{MapData, MapError};
+
+pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> {
+    let max_entries = map.obj.max_entries();
+    if index >= map.obj.max_entries() {
+        Err(MapError::OutOfBounds { index, max_entries })
+    } else {
+        Ok(())
+    }
+}

+ 23 - 49
aya/src/maps/array/per_cpu_array.rs

@@ -1,12 +1,11 @@
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
     mem,
-    ops::{Deref, DerefMut},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_PERCPU_ARRAY,
-    maps::{IterableMap, Map, MapError, MapRef, MapRefMut, PerCpuValues},
+    maps::{array, IterableMap, MapData, MapError, PerCpuValues},
     sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
     Pod,
 };
@@ -31,11 +30,11 @@ use crate::{
 /// #     #[error(transparent)]
 /// #     Bpf(#[from] aya::BpfError)
 /// # }
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::{PerCpuArray, PerCpuValues};
 /// use aya::util::nr_cpus;
 ///
-/// let mut array = PerCpuArray::try_from(bpf.map_mut("ARRAY")?)?;
+/// let mut array: PerCpuArray<_,u32> = bpf.map_mut("ARRAY")?.try_into()?;
 ///
 /// // set array[1] = 42 for all cpus
 /// let nr_cpus = nr_cpus()?;
@@ -50,29 +49,26 @@ use crate::{
 /// # Ok::<(), Error>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_PERCPU_ARRAY")]
-pub struct PerCpuArray<T: Deref<Target = Map>, V: Pod> {
+pub struct PerCpuArray<T, V: Pod> {
     inner: T,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, V: Pod> PerCpuArray<T, V> {
-    fn new(map: T) -> Result<PerCpuArray<T, V>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_PERCPU_ARRAY as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>, V: Pod> PerCpuArray<T, V> {
+    pub(crate) fn new(map: T) -> Result<PerCpuArray<T, V>, MapError> {
+        let data = map.as_ref();
         let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
 
         let expected = mem::size_of::<V>();
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(PerCpuArray {
             inner: map,
@@ -84,7 +80,7 @@ impl<T: Deref<Target = Map>, V: Pod> PerCpuArray<T, V> {
     ///
     /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
     pub fn len(&self) -> u32 {
-        self.inner.obj.max_entries()
+        self.inner.as_ref().obj.max_entries()
     }
 
     /// Returns a slice of values - one for each CPU - stored at the given index.
@@ -94,8 +90,9 @@ impl<T: Deref<Target = Map>, V: Pod> PerCpuArray<T, V> {
     /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
     /// if `bpf_map_lookup_elem` fails.
     pub fn get(&self, index: &u32, flags: u64) -> Result<PerCpuValues<V>, MapError> {
-        self.check_bounds(*index)?;
-        let fd = self.inner.fd_or_err()?;
+        let data = self.inner.as_ref();
+        array::check_bounds(data, *index)?;
+        let fd = data.fd_or_err()?;
 
         let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
@@ -111,18 +108,9 @@ impl<T: Deref<Target = Map>, V: Pod> PerCpuArray<T, V> {
     pub fn iter(&self) -> impl Iterator<Item = Result<PerCpuValues<V>, MapError>> + '_ {
         (0..self.len()).map(move |i| self.get(&i, 0))
     }
-
-    fn check_bounds(&self, index: u32) -> Result<(), MapError> {
-        let max_entries = self.inner.obj.max_entries();
-        if index >= self.inner.obj.max_entries() {
-            Err(MapError::OutOfBounds { index, max_entries })
-        } else {
-            Ok(())
-        }
-    }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> PerCpuArray<T, V> {
+impl<T: AsMut<MapData>, V: Pod> PerCpuArray<T, V> {
     /// Sets the values - one for each CPU - at the given index.
     ///
     /// # Errors
@@ -130,8 +118,10 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> PerCpuArray<T, V>
     /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
     /// if `bpf_map_update_elem` fails.
     pub fn set(&mut self, index: u32, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
-        self.check_bounds(index)?;
+        let data = self.inner.as_mut();
+        array::check_bounds(data, index)?;
+        let fd = data.fd_or_err()?;
+
         bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_update_elem".to_owned(),
@@ -142,28 +132,12 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> PerCpuArray<T, V>
     }
 }
 
-impl<T: Deref<Target = Map>, V: Pod> IterableMap<u32, PerCpuValues<V>> for PerCpuArray<T, V> {
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>, V: Pod> IterableMap<u32, PerCpuValues<V>> for PerCpuArray<T, V> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, index: &u32) -> Result<PerCpuValues<V>, MapError> {
         self.get(index, 0)
     }
 }
-
-impl<V: Pod> TryFrom<MapRef> for PerCpuArray<MapRef, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<PerCpuArray<MapRef, V>, MapError> {
-        PerCpuArray::new(a)
-    }
-}
-
-impl<V: Pod> TryFrom<MapRefMut> for PerCpuArray<MapRefMut, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<PerCpuArray<MapRefMut, V>, MapError> {
-        PerCpuArray::new(a)
-    }
-}

+ 19 - 45
aya/src/maps/array/program_array.rs

@@ -1,14 +1,13 @@
 //! An array of eBPF program file descriptors used as a jump table.
 
 use std::{
+    convert::{AsMut, AsRef},
     mem,
-    ops::{Deref, DerefMut},
     os::unix::prelude::{AsRawFd, RawFd},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY,
-    maps::{Map, MapError, MapKeys, MapRef, MapRefMut},
+    maps::{array, MapData, MapError, MapKeys},
     programs::ProgramFd,
     sys::{bpf_map_delete_elem, bpf_map_update_elem},
 };
@@ -29,7 +28,7 @@ use crate::{
 /// use aya::maps::ProgramArray;
 /// use aya::programs::CgroupSkb;
 ///
-/// let mut prog_array = ProgramArray::try_from(bpf.map_mut("JUMP_TABLE")?)?;
+/// let mut prog_array: ProgramArray<_> = bpf.take_map("JUMP_TABLE")?.try_into()?;
 /// let prog_0: &CgroupSkb = bpf.program("example_prog_0").unwrap().try_into()?;
 /// let prog_0_fd =  prog_0.fd().unwrap();
 /// let prog_1: &CgroupSkb = bpf.program("example_prog_1").unwrap().try_into()?;
@@ -49,28 +48,25 @@ use crate::{
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
-pub struct ProgramArray<T: Deref<Target = Map>> {
+pub struct ProgramArray<T> {
     inner: T,
 }
 
-impl<T: Deref<Target = Map>> ProgramArray<T> {
-    fn new(map: T) -> Result<ProgramArray<T>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_PROG_ARRAY as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>> ProgramArray<T> {
+    pub(crate) fn new(map: T) -> Result<ProgramArray<T>, MapError> {
+        let data = map.as_ref();
         let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
 
         let expected = mem::size_of::<RawFd>();
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(ProgramArray { inner: map })
     }
@@ -78,27 +74,19 @@ impl<T: Deref<Target = Map>> ProgramArray<T> {
     /// An iterator over the indices of the array that point to a program. The iterator item type
     /// is `Result<u32, MapError>`.
     pub fn indices(&self) -> MapKeys<'_, u32> {
-        MapKeys::new(&self.inner)
-    }
-
-    fn check_bounds(&self, index: u32) -> Result<(), MapError> {
-        let max_entries = self.inner.obj.max_entries();
-        if index >= self.inner.obj.max_entries() {
-            Err(MapError::OutOfBounds { index, max_entries })
-        } else {
-            Ok(())
-        }
+        MapKeys::new(self.inner.as_ref())
     }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
+impl<T: AsMut<MapData>> ProgramArray<T> {
     /// Sets the target program file descriptor for the given index in the jump table.
     ///
     /// When an eBPF program calls `bpf_tail_call(ctx, prog_array, index)`, control
     /// flow will jump to `program`.
     pub fn set(&mut self, index: u32, program: ProgramFd, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
-        self.check_bounds(index)?;
+        let data = self.inner.as_mut();
+        array::check_bounds(data, index)?;
+        let fd = data.fd_or_err()?;
         let prog_fd = program.as_raw_fd();
 
         bpf_map_update_elem(fd, Some(&index), &prog_fd, flags).map_err(|(_, io_error)| {
@@ -115,8 +103,10 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
     /// Calling `bpf_tail_call(ctx, prog_array, index)` on an index that has been cleared returns an
     /// error.
     pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
-        self.check_bounds(*index)?;
+        let data = self.inner.as_mut();
+        array::check_bounds(data, *index)?;
+        let fd = self.inner.as_mut().fd_or_err()?;
+
         bpf_map_delete_elem(fd, index)
             .map(|_| ())
             .map_err(|(_, io_error)| MapError::SyscallError {
@@ -125,19 +115,3 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> ProgramArray<T> {
             })
     }
 }
-
-impl TryFrom<MapRef> for ProgramArray<MapRef> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<ProgramArray<MapRef>, MapError> {
-        ProgramArray::new(a)
-    }
-}
-
-impl TryFrom<MapRefMut> for ProgramArray<MapRefMut> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<ProgramArray<MapRefMut>, MapError> {
-        ProgramArray::new(a)
-    }
-}

+ 26 - 60
aya/src/maps/bloom_filter.rs

@@ -1,11 +1,10 @@
 //! A Bloom Filter.
-use std::{marker::PhantomData, ops::Deref};
+use std::{convert::AsRef, marker::PhantomData};
 
 use core::mem;
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_BLOOM_FILTER,
-    maps::{Map, MapError, MapRef, MapRefMut},
+    maps::{MapData, MapError},
     sys::{bpf_map_lookup_elem_ptr, bpf_map_push_elem},
     Pod,
 };
@@ -19,10 +18,10 @@ use crate::{
 /// # Examples
 ///
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::bloom_filter::BloomFilter;
 ///
-/// let mut bloom_filter = BloomFilter::try_from(bpf.map_mut("BLOOM_FILTER")?)?;
+/// let mut bloom_filter: BloomFilter<_,u32> = bpf.map_mut("BLOOM_FILTER")?.try_into()?;
 ///
 /// bloom_filter.insert(1, 0)?;
 ///
@@ -33,27 +32,21 @@ use crate::{
 /// ```
 
 #[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")]
-pub struct BloomFilter<T: Deref<Target = Map>, V: Pod> {
+pub struct BloomFilter<T, V: Pod> {
     inner: T,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, V: Pod> BloomFilter<T, V> {
+impl<T: AsRef<MapData>, V: Pod> BloomFilter<T, V> {
     pub(crate) fn new(map: T) -> Result<BloomFilter<T, V>, MapError> {
-        let map_type = map.obj.map_type();
-
-        // validate the map definition
-        if map_type != BPF_MAP_TYPE_BLOOM_FILTER as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
-
+        let data = map.as_ref();
         let size = mem::size_of::<V>();
-        let expected = map.obj.value_size() as usize;
+        let expected = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         };
 
-        let _ = map.fd_or_err()?;
+        let _ = data.fd_or_err()?;
 
         Ok(BloomFilter {
             inner: map,
@@ -63,7 +56,7 @@ impl<T: Deref<Target = Map>, V: Pod> BloomFilter<T, V> {
 
     /// Query the existence of the element.
     pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
 
         bpf_map_lookup_elem_ptr::<u32, _>(fd, None, &mut value, flags)
             .map_err(|(_, io_error)| MapError::SyscallError {
@@ -76,7 +69,7 @@ impl<T: Deref<Target = Map>, V: Pod> BloomFilter<T, V> {
 
     /// Inserts a value into the map.
     pub fn insert(&self, value: V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         bpf_map_push_elem(fd, &value, flags).map_err(|(_, io_error)| MapError::SyscallError {
             call: "bpf_map_push_elem".to_owned(),
             io_error,
@@ -85,38 +78,6 @@ impl<T: Deref<Target = Map>, V: Pod> BloomFilter<T, V> {
     }
 }
 
-impl<V: Pod> TryFrom<MapRef> for BloomFilter<MapRef, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<BloomFilter<MapRef, V>, MapError> {
-        BloomFilter::new(a)
-    }
-}
-
-impl<V: Pod> TryFrom<MapRefMut> for BloomFilter<MapRefMut, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<BloomFilter<MapRefMut, V>, MapError> {
-        BloomFilter::new(a)
-    }
-}
-
-impl<'a, V: Pod> TryFrom<&'a Map> for BloomFilter<&'a Map, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a Map) -> Result<BloomFilter<&'a Map, V>, MapError> {
-        BloomFilter::new(a)
-    }
-}
-
-impl<'a, V: Pod> TryFrom<&'a mut Map> for BloomFilter<&'a mut Map, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a mut Map) -> Result<BloomFilter<&'a mut Map, V>, MapError> {
-        BloomFilter::new(a)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -126,6 +87,7 @@ mod tests {
             bpf_cmd,
             bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
         },
+        maps::{Map, MapData},
         obj,
         sys::{override_syscall, SysResult, Syscall},
     };
@@ -154,7 +116,7 @@ mod tests {
 
     #[test]
     fn test_wrong_value_size() {
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -171,7 +133,7 @@ mod tests {
 
     #[test]
     fn test_try_from_wrong_map() {
-        let map = Map {
+        let map_data = MapData {
             obj: obj::Map::Legacy(obj::LegacyMap {
                 def: bpf_map_def {
                     map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
@@ -190,15 +152,17 @@ mod tests {
             btf_fd: None,
         };
 
+        let map = Map::PerfEventArray(map_data);
+
         assert!(matches!(
             BloomFilter::<_, u32>::try_from(&map),
-            Err(MapError::InvalidMapType { .. })
+            Err(MapError::UnexpectedMapType)
         ));
     }
 
     #[test]
     fn test_new_not_created() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -213,7 +177,7 @@ mod tests {
 
     #[test]
     fn test_new_ok() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -225,12 +189,14 @@ mod tests {
 
     #[test]
     fn test_try_from_ok() {
-        let map = Map {
+        let map_data = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
+
+        let map = Map::BloomFilter(map_data);
         assert!(BloomFilter::<_, u32>::try_from(&map).is_ok())
     }
 
@@ -238,7 +204,7 @@ mod tests {
     fn test_insert_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -262,7 +228,7 @@ mod tests {
             _ => sys_error(EFAULT),
         });
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -276,7 +242,7 @@ mod tests {
     #[test]
     fn test_contains_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -299,7 +265,7 @@ mod tests {
             } => sys_error(ENOENT),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,

+ 67 - 91
aya/src/maps/hash_map/hash_map.rs

@@ -1,11 +1,10 @@
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
-    ops::{Deref, DerefMut},
 };
 
 use crate::{
-    generated::bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH},
-    maps::{hash_map, IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut},
+    maps::{hash_map, IterableMap, MapData, MapError, MapIter, MapKeys},
     sys::bpf_map_lookup_elem,
     Pod,
 };
@@ -19,10 +18,10 @@ use crate::{
 /// # Examples
 ///
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::HashMap;
 ///
-/// let mut redirect_ports = HashMap::try_from(bpf.map_mut("REDIRECT_PORTS")?)?;
+/// let mut redirect_ports: HashMap<_, u32, u32> = bpf.map_mut("REDIRECT_PORTS")?.try_into()?;
 ///
 /// // redirect port 80 to 8080
 /// redirect_ports.insert(80, 8080, 0);
@@ -32,22 +31,18 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_HASH")]
 #[doc(alias = "BPF_MAP_TYPE_LRU_HASH")]
-pub struct HashMap<T: Deref<Target = Map>, K, V> {
+#[derive(Debug)]
+pub struct HashMap<T, K, V> {
     inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
+impl<T: AsRef<MapData>, K: Pod, V: Pod> HashMap<T, K, V> {
     pub(crate) fn new(map: T) -> Result<HashMap<T, K, V>, MapError> {
-        let map_type = map.obj.map_type();
-
-        // validate the map definition
-        if map_type != BPF_MAP_TYPE_HASH as u32 && map_type != BPF_MAP_TYPE_LRU_HASH as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
-        hash_map::check_kv_size::<K, V>(&map)?;
-        let _ = map.fd_or_err()?;
+        let data = map.as_ref();
+        hash_map::check_kv_size::<K, V>(data)?;
+        let _ = data.fd_or_err()?;
 
         Ok(HashMap {
             inner: map,
@@ -58,7 +53,7 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
 
     /// Returns a copy of the value associated with the key.
     pub fn get(&self, key: &K, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_lookup_elem".to_owned(),
@@ -77,25 +72,25 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
     /// An iterator visiting all keys in arbitrary order. The iterator element
     /// type is `Result<K, MapError>`.
     pub fn keys(&self) -> MapKeys<'_, K> {
-        MapKeys::new(&self.inner)
+        MapKeys::new(self.inner.as_ref())
     }
 }
 
-impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
+impl<T: AsMut<MapData>, K: Pod, V: Pod> HashMap<T, K, V> {
     /// Inserts a key-value pair into the map.
     pub fn insert(&mut self, key: K, value: V, flags: u64) -> Result<(), MapError> {
-        hash_map::insert(&mut self.inner, key, value, flags)
+        hash_map::insert(self.inner.as_mut(), key, value, flags)
     }
 
     /// Removes a key from the map.
     pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
-        hash_map::remove(&mut self.inner, key)
+        hash_map::remove(self.inner.as_mut(), key)
     }
 }
 
-impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, key: &K) -> Result<V, MapError> {
@@ -103,38 +98,6 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K,
     }
 }
 
-impl<K: Pod, V: Pod> TryFrom<MapRef> for HashMap<MapRef, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<HashMap<MapRef, K, V>, MapError> {
-        HashMap::new(a)
-    }
-}
-
-impl<K: Pod, V: Pod> TryFrom<MapRefMut> for HashMap<MapRefMut, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<HashMap<MapRefMut, K, V>, MapError> {
-        HashMap::new(a)
-    }
-}
-
-impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a Map) -> Result<HashMap<&'a Map, K, V>, MapError> {
-        HashMap::new(a)
-    }
-}
-
-impl<'a, K: Pod, V: Pod> TryFrom<&'a mut Map> for HashMap<&'a mut Map, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a mut Map) -> Result<HashMap<&'a mut Map, K, V>, MapError> {
-        HashMap::new(a)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use std::io;
@@ -145,8 +108,9 @@ mod tests {
         bpf_map_def,
         generated::{
             bpf_attr, bpf_cmd,
-            bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
+            bpf_map_type::{BPF_MAP_TYPE_HASH, BPF_MAP_TYPE_LRU_HASH},
         },
+        maps::{Map, MapData},
         obj,
         sys::{override_syscall, SysResult, Syscall},
     };
@@ -175,7 +139,7 @@ mod tests {
 
     #[test]
     fn test_wrong_key_size() {
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -192,7 +156,7 @@ mod tests {
 
     #[test]
     fn test_wrong_value_size() {
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -209,34 +173,42 @@ mod tests {
 
     #[test]
     fn test_try_from_wrong_map() {
-        let map = Map {
-            obj: obj::Map::Legacy(obj::LegacyMap {
-                def: bpf_map_def {
-                    map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
-                    key_size: 4,
-                    value_size: 4,
-                    max_entries: 1024,
-                    ..Default::default()
-                },
-                section_index: 0,
-                symbol_index: 0,
-                data: Vec::new(),
-                kind: obj::MapKind::Other,
-            }),
+        let map_data = MapData {
+            obj: new_obj_map(),
+            fd: None,
+            pinned: false,
+            btf_fd: None,
+        };
+
+        let map = Map::Array(map_data);
+        assert!(matches!(
+            HashMap::<_, u8, u32>::try_from(&map),
+            Err(MapError::UnexpectedMapType)
+        ));
+    }
+
+    #[test]
+    fn test_try_from_wrong_map_values() {
+        let map_data = MapData {
+            obj: new_obj_map(),
             fd: None,
             pinned: false,
             btf_fd: None,
         };
 
+        let map = Map::HashMap(map_data);
         assert!(matches!(
-            HashMap::<_, u32, u32>::try_from(&map),
-            Err(MapError::InvalidMapType { .. })
+            HashMap::<_, u32, u16>::try_from(&map),
+            Err(MapError::InvalidValueSize {
+                size: 2,
+                expected: 4
+            })
         ));
     }
 
     #[test]
     fn test_new_not_created() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -251,7 +223,7 @@ mod tests {
 
     #[test]
     fn test_new_ok() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -263,18 +235,20 @@ mod tests {
 
     #[test]
     fn test_try_from_ok() {
-        let map = Map {
+        let map_data = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
+
+        let map = Map::HashMap(map_data);
         assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok())
     }
 
     #[test]
     fn test_try_from_ok_lru() {
-        let map = Map {
+        let map_data = MapData {
             obj: obj::Map::Legacy(obj::LegacyMap {
                 def: bpf_map_def {
                     map_type: BPF_MAP_TYPE_LRU_HASH as u32,
@@ -293,6 +267,8 @@ mod tests {
             btf_fd: None,
         };
 
+        let map = Map::HashMap(map_data);
+
         assert!(HashMap::<_, u32, u32>::try_from(&map).is_ok())
     }
 
@@ -300,7 +276,7 @@ mod tests {
     fn test_insert_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -324,7 +300,7 @@ mod tests {
             _ => sys_error(EFAULT),
         });
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -339,7 +315,7 @@ mod tests {
     fn test_remove_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -363,7 +339,7 @@ mod tests {
             _ => sys_error(EFAULT),
         });
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -377,7 +353,7 @@ mod tests {
     #[test]
     fn test_get_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -400,7 +376,7 @@ mod tests {
             } => sys_error(ENOENT),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -437,7 +413,7 @@ mod tests {
             } => sys_error(ENOENT),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -486,7 +462,7 @@ mod tests {
             _ => sys_error(EFAULT),
         });
 
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -519,7 +495,7 @@ mod tests {
             }
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -554,7 +530,7 @@ mod tests {
             } => lookup_elem(attr),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -592,7 +568,7 @@ mod tests {
             }
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -631,7 +607,7 @@ mod tests {
             } => lookup_elem(attr),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -676,7 +652,7 @@ mod tests {
             }
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,

+ 11 - 4
aya/src/maps/hash_map/mod.rs

@@ -2,7 +2,7 @@
 use std::mem;
 
 use crate::{
-    maps::{Map, MapError},
+    maps::MapError,
     sys::{bpf_map_delete_elem, bpf_map_update_elem},
 };
 
@@ -13,7 +13,9 @@ mod per_cpu_hash_map;
 pub use hash_map::*;
 pub use per_cpu_hash_map::*;
 
-pub(crate) fn check_kv_size<K, V>(map: &Map) -> Result<(), MapError> {
+use super::MapData;
+
+pub(crate) fn check_kv_size<K, V>(map: &MapData) -> Result<(), MapError> {
     let size = mem::size_of::<K>();
     let expected = map.obj.key_size() as usize;
     if size != expected {
@@ -27,7 +29,12 @@ pub(crate) fn check_kv_size<K, V>(map: &Map) -> Result<(), MapError> {
     Ok(())
 }
 
-pub(crate) fn insert<K, V>(map: &mut Map, key: K, value: V, flags: u64) -> Result<(), MapError> {
+pub(crate) fn insert<K, V>(
+    map: &mut MapData,
+    key: K,
+    value: V,
+    flags: u64,
+) -> Result<(), MapError> {
     let fd = map.fd_or_err()?;
     bpf_map_update_elem(fd, Some(&key), &value, flags).map_err(|(_, io_error)| {
         MapError::SyscallError {
@@ -39,7 +46,7 @@ pub(crate) fn insert<K, V>(map: &mut Map, key: K, value: V, flags: u64) -> Resul
     Ok(())
 }
 
-pub(crate) fn remove<K>(map: &mut Map, key: &K) -> Result<(), MapError> {
+pub(crate) fn remove<K>(map: &mut MapData, key: &K) -> Result<(), MapError> {
     let fd = map.fd_or_err()?;
     bpf_map_delete_elem(fd, key)
         .map(|_| ())

+ 18 - 53
aya/src/maps/hash_map/per_cpu_hash_map.rs

@@ -1,14 +1,12 @@
 //! Per-CPU hash map.
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
-    ops::{Deref, DerefMut},
 };
 
 use crate::{
     generated::bpf_map_type::{BPF_MAP_TYPE_LRU_PERCPU_HASH, BPF_MAP_TYPE_PERCPU_HASH},
-    maps::{
-        hash_map, IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut, PerCpuValues,
-    },
+    maps::{hash_map, IterableMap, MapData, MapError, MapIter, MapKeys, PerCpuValues},
     sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
     Pod,
 };
@@ -42,15 +40,16 @@ use crate::{
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_LRU_PERCPU_HASH")]
 #[doc(alias = "BPF_MAP_TYPE_PERCPU_HASH")]
-pub struct PerCpuHashMap<T: Deref<Target = Map>, K: Pod, V: Pod> {
+pub struct PerCpuHashMap<T, K: Pod, V: Pod> {
     inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
+impl<T: AsRef<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
     pub(crate) fn new(map: T) -> Result<PerCpuHashMap<T, K, V>, MapError> {
-        let map_type = map.obj.map_type();
+        let data = map.as_ref();
+        let map_type = data.obj.map_type();
 
         // validate the map definition
         if map_type != BPF_MAP_TYPE_PERCPU_HASH as u32
@@ -58,8 +57,8 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
         {
             return Err(MapError::InvalidMapType { map_type });
         }
-        hash_map::check_kv_size::<K, V>(&map)?;
-        let _ = map.fd_or_err()?;
+        hash_map::check_kv_size::<K, V>(data)?;
+        let _ = data.fd_or_err()?;
 
         Ok(PerCpuHashMap {
             inner: map,
@@ -70,7 +69,7 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
 
     /// Returns a slice of values - one for each CPU - associated with the key.
     pub fn get(&self, key: &K, flags: u64) -> Result<PerCpuValues<V>, MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_lookup_elem".to_owned(),
@@ -89,11 +88,11 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
     /// An iterator visiting all keys in arbitrary order. The iterator element
     /// type is `Result<K, MapError>`.
     pub fn keys(&self) -> MapKeys<'_, K> {
-        MapKeys::new(&self.inner)
+        MapKeys::new(self.inner.as_ref())
     }
 }
 
-impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
+impl<T: AsMut<MapData>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
     /// Inserts a slice of values - one for each CPU - for the given key.
     ///
     /// # Examples
@@ -108,13 +107,13 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
     /// #     #[error(transparent)]
     /// #     Bpf(#[from] aya::BpfError)
     /// # }
-    /// # let bpf = aya::Bpf::load(&[])?;
+    /// # let mut bpf = aya::Bpf::load(&[])?;
     /// use aya::maps::{PerCpuHashMap, PerCpuValues};
     /// use aya::util::nr_cpus;
     ///
     /// const RETRIES: u8 = 1;
     ///
-    /// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map_mut("PER_CPU_STORAGE")?)?;
+    /// let mut hm: PerCpuHashMap::<_, u8, u32> = bpf.map_mut("PER_CPU_STORAGE")?.try_into()?;
     /// hm.insert(
     ///     RETRIES,
     ///     PerCpuValues::try_from(vec![3u32; nr_cpus()?])?,
@@ -123,7 +122,7 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
     /// # Ok::<(), Error>(())
     /// ```
     pub fn insert(&mut self, key: K, values: PerCpuValues<V>, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_mut().fd_or_err()?;
         bpf_map_update_elem_per_cpu(fd, &key, &values, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_update_elem".to_owned(),
@@ -136,50 +135,16 @@ impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> PerCpuHashMap<T, K, V> {
 
     /// Removes a key from the map.
     pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
-        hash_map::remove(&mut self.inner, key)
+        hash_map::remove(self.inner.as_mut(), key)
     }
 }
 
-impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>>
-    for PerCpuHashMap<T, K, V>
-{
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>, K: Pod, V: Pod> IterableMap<K, PerCpuValues<V>> for PerCpuHashMap<T, K, V> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, key: &K) -> Result<PerCpuValues<V>, MapError> {
         PerCpuHashMap::get(self, key, 0)
     }
 }
-
-impl<K: Pod, V: Pod> TryFrom<MapRef> for PerCpuHashMap<MapRef, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<PerCpuHashMap<MapRef, K, V>, MapError> {
-        PerCpuHashMap::new(a)
-    }
-}
-
-impl<K: Pod, V: Pod> TryFrom<MapRefMut> for PerCpuHashMap<MapRefMut, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<PerCpuHashMap<MapRefMut, K, V>, MapError> {
-        PerCpuHashMap::new(a)
-    }
-}
-
-impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for PerCpuHashMap<&'a Map, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a Map) -> Result<PerCpuHashMap<&'a Map, K, V>, MapError> {
-        PerCpuHashMap::new(a)
-    }
-}
-
-impl<'a, K: Pod, V: Pod> TryFrom<&'a mut Map> for PerCpuHashMap<&'a mut Map, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a mut Map) -> Result<PerCpuHashMap<&'a mut Map, K, V>, MapError> {
-        PerCpuHashMap::new(a)
-    }
-}

+ 46 - 73
aya/src/maps/lpm_trie.rs

@@ -1,9 +1,12 @@
 //! A LPM Trie.
-use std::{marker::PhantomData, mem, ops::Deref};
+use std::{
+    convert::{AsMut, AsRef},
+    marker::PhantomData,
+    mem,
+};
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_LPM_TRIE,
-    maps::{IterableMap, Map, MapError, MapRef, MapRefMut},
+    maps::{IterableMap, MapData, MapError},
     sys::{bpf_map_delete_elem, bpf_map_lookup_elem, bpf_map_update_elem},
     Pod,
 };
@@ -17,11 +20,11 @@ use crate::{
 /// # Examples
 ///
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::lpm_trie::{LpmTrie, Key};
 /// use std::net::Ipv4Addr;
 ///
-/// let mut trie = LpmTrie::try_from(bpf.map_mut("LPM_TRIE")?)?;
+/// let mut trie: LpmTrie<_,u32,u32> = bpf.map_mut("LPM_TRIE")?.try_into()?;
 /// let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
 /// // The following represents a key for the "8.8.8.8/16" subnet.
 /// // The first argument - the prefix length - represents how many bytes should be matched against. The second argument is the actual data to be matched.
@@ -43,7 +46,7 @@ use crate::{
 /// ```
 
 #[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")]
-pub struct LpmTrie<T: Deref<Target = Map>, K, V> {
+pub struct LpmTrie<T, K, V> {
     inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
@@ -96,26 +99,21 @@ impl<K: Pod> Clone for Key<K> {
 // A Pod impl is required as Key struct is a key for a map.
 unsafe impl<K: Pod> Pod for Key<K> {}
 
-impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
+impl<T: AsRef<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
     pub(crate) fn new(map: T) -> Result<LpmTrie<T, K, V>, MapError> {
-        let map_type = map.obj.map_type();
-
-        // validate the map definition
-        if map_type != BPF_MAP_TYPE_LPM_TRIE as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+        let data = map.as_ref();
         let size = mem::size_of::<Key<K>>();
-        let expected = map.obj.key_size() as usize;
+        let expected = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
         let size = mem::size_of::<V>();
-        let expected = map.obj.value_size() as usize;
+        let expected = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         };
 
-        let _ = map.fd_or_err()?;
+        let _ = data.fd_or_err()?;
 
         Ok(LpmTrie {
             inner: map,
@@ -126,7 +124,7 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
 
     /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
     pub fn get(&self, key: &Key<K>, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_lookup_elem".to_owned(),
@@ -135,10 +133,12 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
         })?;
         value.ok_or(MapError::KeyNotFound)
     }
+}
 
+impl<T: AsMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
     /// Inserts a key value pair into the map.
-    pub fn insert(&self, key: &Key<K>, value: V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+    pub fn insert(&mut self, key: &Key<K>, value: V, flags: u64) -> Result<(), MapError> {
+        let fd = self.inner.as_mut().fd_or_err()?;
         bpf_map_update_elem(fd, Some(key), &value, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_update_elem".to_owned(),
@@ -152,8 +152,8 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
     /// Removes an element from the map.
     ///
     /// Both the prefix and data must match exactly - this method does not do a longest prefix match.
-    pub fn remove(&self, key: &Key<K>) -> Result<(), MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+    pub fn remove(&mut self, key: &Key<K>) -> Result<(), MapError> {
+        let fd = self.inner.as_mut().fd_or_err()?;
         bpf_map_delete_elem(fd, key)
             .map(|_| ())
             .map_err(|(_, io_error)| MapError::SyscallError {
@@ -163,9 +163,9 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
     }
 }
 
-impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for LpmTrie<T, K, V> {
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>, K: Pod, V: Pod> IterableMap<K, V> for LpmTrie<T, K, V> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, key: &K) -> Result<V, MapError> {
@@ -174,38 +174,6 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for LpmTrie<T, K,
     }
 }
 
-impl<K: Pod, V: Pod> TryFrom<MapRef> for LpmTrie<MapRef, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<LpmTrie<MapRef, K, V>, MapError> {
-        LpmTrie::new(a)
-    }
-}
-
-impl<K: Pod, V: Pod> TryFrom<MapRefMut> for LpmTrie<MapRefMut, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<LpmTrie<MapRefMut, K, V>, MapError> {
-        LpmTrie::new(a)
-    }
-}
-
-impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for LpmTrie<&'a Map, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a Map) -> Result<LpmTrie<&'a Map, K, V>, MapError> {
-        LpmTrie::new(a)
-    }
-}
-
-impl<'a, K: Pod, V: Pod> TryFrom<&'a mut Map> for LpmTrie<&'a mut Map, K, V> {
-    type Error = MapError;
-
-    fn try_from(a: &'a mut Map) -> Result<LpmTrie<&'a mut Map, K, V>, MapError> {
-        LpmTrie::new(a)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -215,6 +183,7 @@ mod tests {
             bpf_cmd,
             bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
         },
+        maps::{Map, MapData},
         obj,
         sys::{override_syscall, SysResult, Syscall},
     };
@@ -243,7 +212,7 @@ mod tests {
 
     #[test]
     fn test_wrong_key_size() {
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -260,7 +229,7 @@ mod tests {
 
     #[test]
     fn test_wrong_value_size() {
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -277,7 +246,7 @@ mod tests {
 
     #[test]
     fn test_try_from_wrong_map() {
-        let map = Map {
+        let map_data = MapData {
             obj: obj::Map::Legacy(obj::LegacyMap {
                 def: bpf_map_def {
                     map_type: BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32,
@@ -296,15 +265,17 @@ mod tests {
             pinned: false,
         };
 
+        let map = Map::PerfEventArray(map_data);
+
         assert!(matches!(
             LpmTrie::<_, u32, u32>::try_from(&map),
-            Err(MapError::InvalidMapType { .. })
+            Err(MapError::UnexpectedMapType)
         ));
     }
 
     #[test]
     fn test_new_not_created() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -319,7 +290,7 @@ mod tests {
 
     #[test]
     fn test_new_ok() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -331,12 +302,14 @@ mod tests {
 
     #[test]
     fn test_try_from_ok() {
-        let map = Map {
+        let map_data = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
+
+        let map = Map::LpmTrie(map_data);
         assert!(LpmTrie::<_, u32, u32>::try_from(&map).is_ok())
     }
 
@@ -344,13 +317,13 @@ mod tests {
     fn test_insert_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
-        let trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
+        let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
         let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
         let key = Key::new(16, u32::from(ipaddr).to_be());
         assert!(matches!(
@@ -369,14 +342,14 @@ mod tests {
             _ => sys_error(EFAULT),
         });
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
 
-        let trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
+        let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
         let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
         let key = Key::new(16, u32::from(ipaddr).to_be());
         assert!(trie.insert(&key, 1, 0).is_ok());
@@ -386,13 +359,13 @@ mod tests {
     fn test_remove_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
-        let trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
+        let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
         let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
         let key = Key::new(16, u32::from(ipaddr).to_be());
         assert!(matches!(
@@ -411,13 +384,13 @@ mod tests {
             _ => sys_error(EFAULT),
         });
 
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
             btf_fd: None,
         };
-        let trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
+        let mut trie = LpmTrie::<_, u32, u32>::new(&mut map).unwrap();
         let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
         let key = Key::new(16, u32::from(ipaddr).to_be());
         assert!(trie.remove(&key).is_ok());
@@ -426,7 +399,7 @@ mod tests {
     #[test]
     fn test_get_syscall_error() {
         override_syscall(|_| sys_error(EFAULT));
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,
@@ -451,7 +424,7 @@ mod tests {
             } => sys_error(ENOENT),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,

+ 0 - 81
aya/src/maps/map_lock.rs

@@ -1,81 +0,0 @@
-use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
-use std::{
-    mem,
-    ops::{Deref, DerefMut},
-    sync::Arc,
-};
-
-use crate::maps::Map;
-
-pub(crate) struct MapLockError;
-
-/* FIXME: write a full RwLock implementation that doesn't use borrowing guards
- * so that try_read() and try_write() don't have to use the ugly lifetime
- * extension hack */
-
-#[derive(Debug)]
-pub(crate) struct MapLock {
-    inner: Arc<RwLock<Map>>,
-}
-
-impl MapLock {
-    pub(crate) fn new(map: Map) -> MapLock {
-        MapLock {
-            inner: Arc::new(RwLock::new(map)),
-        }
-    }
-
-    pub(crate) fn try_read(&self) -> Result<MapRef, MapLockError> {
-        let lock: Option<RwLockReadGuard<'static, Map>> =
-            unsafe { mem::transmute(self.inner.try_read()) };
-        lock.map(|guard| MapRef {
-            _lock: self.inner.clone(),
-            guard,
-        })
-        .ok_or(MapLockError)
-    }
-
-    pub(crate) fn try_write(&self) -> Result<MapRefMut, MapLockError> {
-        let lock: Option<RwLockWriteGuard<'static, Map>> =
-            unsafe { mem::transmute(self.inner.try_write()) };
-        lock.map(|guard| MapRefMut {
-            _lock: self.inner.clone(),
-            guard,
-        })
-        .ok_or(MapLockError)
-    }
-}
-
-/// A borrowed reference to a BPF map.
-pub struct MapRef {
-    _lock: Arc<RwLock<Map>>,
-    guard: RwLockReadGuard<'static, Map>,
-}
-
-/// A mutable borrowed reference to a BPF map.
-pub struct MapRefMut {
-    _lock: Arc<RwLock<Map>>,
-    guard: RwLockWriteGuard<'static, Map>,
-}
-
-impl Deref for MapRef {
-    type Target = Map;
-
-    fn deref(&self) -> &Map {
-        &self.guard
-    }
-}
-
-impl Deref for MapRefMut {
-    type Target = Map;
-
-    fn deref(&self) -> &Map {
-        &self.guard
-    }
-}
-
-impl DerefMut for MapRefMut {
-    fn deref_mut(&mut self) -> &mut Map {
-        &mut self.guard
-    }
-}

+ 214 - 36
aya/src/maps/mod.rs

@@ -4,22 +4,25 @@
 //! used to setup and share data with eBPF programs. When you call
 //! [`Bpf::load_file`](crate::Bpf::load_file) or
 //! [`Bpf::load`](crate::Bpf::load), all the maps defined in the eBPF code get
-//! initialized and can then be accessed using [`Bpf::map`](crate::Bpf::map) and
-//! [`Bpf::map_mut`](crate::Bpf::map_mut).
+//! initialized and can then be accessed using [`Bpf::map`](crate::Bpf::map),
+//! [`Bpf::map_mut`](crate::Bpf::map_mut), [`Bpf::take_map`](crate::Bpf::map)
+//! or [`Bpf::map_mut`](crate::Bpf::take_map).
 //!
 //! # Typed maps
 //!
 //! The eBPF API includes many map types each supporting different operations.
-//! [`Bpf::map`](crate::Bpf::map) and [`Bpf::map_mut`](crate::Bpf::map_mut) always return the
-//! opaque [`MapRef`] and [`MapRefMut`] types respectively. Those two types can be converted to
-//! *typed maps* using the [`TryFrom`](std::convert::TryFrom) trait. For example:
+//! [`Bpf::map`](crate::Bpf::map), [`Bpf::map_mut`](crate::Bpf::map_mut), and
+//! [`Bpf::map_mut`](crate::Bpf::take_map) always return the
+//! opaque [`&Map`], [`&mut Map`], and [`Map`] types respectively. Those three types can be converted to
+//! *typed maps* using the [`TryFrom`](std::convert::TryFrom) or [`TryInto`](std::convert::TryInto)
+//! trait. For example:
 //!
 //! ```no_run
 //! # let mut bpf = aya::Bpf::load(&[])?;
 //! use aya::maps::SockMap;
 //! use aya::programs::SkMsg;
 //!
-//! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
+//! let intercept_egress: SockMap<_> = bpf.take_map("INTERCEPT_EGRESS")?.try_into()?;
 //! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 //! prog.load()?;
 //! prog.attach(&intercept_egress)?;
@@ -32,6 +35,7 @@
 //! versa. Because of that, all map values must be plain old data and therefore
 //! implement the [Pod] trait.
 use std::{
+    convert::{AsMut, AsRef},
     ffi::CString,
     fmt, io,
     marker::PhantomData,
@@ -58,8 +62,6 @@ use crate::{
     PinningType, Pod,
 };
 
-mod map_lock;
-
 pub mod array;
 pub mod bloom_filter;
 pub mod hash_map;
@@ -71,8 +73,11 @@ pub mod stack;
 pub mod stack_trace;
 
 pub use array::{Array, PerCpuArray, ProgramArray};
+pub use bloom_filter::BloomFilter;
 pub use hash_map::{HashMap, PerCpuHashMap};
-pub use map_lock::*;
+pub use lpm_trie::LpmTrie;
+#[cfg(any(feature = "async", doc))]
+pub use perf::AsyncPerfEventArray;
 pub use perf::PerfEventArray;
 pub use queue::Queue;
 pub use sock::{SockHash, SockMap};
@@ -174,20 +179,6 @@ pub enum MapError {
         io_error: io::Error,
     },
 
-    /// Map is borrowed mutably
-    #[error("map `{name}` is borrowed mutably")]
-    BorrowError {
-        /// Map name
-        name: String,
-    },
-
-    /// Map is already borrowed
-    #[error("map `{name}` is already borrowed")]
-    BorrowMutError {
-        /// Map name
-        name: String,
-    },
-
     /// Could not pin map by name
     #[error("map `{name:?}` requested pinning by name. pinning failed")]
     PinError {
@@ -197,6 +188,10 @@ pub enum MapError {
         #[source]
         error: PinError,
     },
+
+    /// The map is not of the expected type.
+    #[error("unexpected map type")]
+    UnexpectedMapType,
 }
 
 /// A map file descriptor.
@@ -243,11 +238,181 @@ fn maybe_warn_rlimit() {
     }
 }
 
+/// eBPF map types.
+#[derive(Debug)]
+pub enum Map {
+    /// A ['Array`] map
+    Array(MapData),
+    /// A [`PerCpuArray`] map
+    PerCpuArray(MapData),
+    /// A [`ProgramArray`] map
+    ProgramArray(MapData),
+    /// A [`HashMap`] map
+    HashMap(MapData),
+    /// A ['PerCpuHashMap'] map
+    PerCpuHashMap(MapData),
+    /// A [`PerfEventArray`] map
+    PerfEventArray(MapData),
+    /// A [`SockMap`] map
+    SockMap(MapData),
+    /// A [`SockHash`] map
+    SockHash(MapData),
+    /// A [`BloomFilter`] map
+    BloomFilter(MapData),
+    /// A [`LpmTrie`] map
+    LpmTrie(MapData),
+    /// A [`Stack`] map
+    Stack(MapData),
+    /// A [`StackTrace`] map
+    StackTraceMap(MapData),
+    /// A [`Queue`] map
+    Queue(MapData),
+}
+
+macro_rules! impl_try_from_map {
+    ($($tx:ident from Map::$ty:ident),+ $(,)?) => {
+        $(
+            impl<'a> TryFrom<&'a Map> for $tx<&'a MapData> {
+                type Error = MapError;
+
+                fn try_from(map: &'a Map) -> Result<$tx<&'a MapData>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $tx::<&'a MapData>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+
+            impl<'a,> TryFrom<&'a mut Map> for $tx<&'a mut MapData> {
+                type Error = MapError;
+
+                fn try_from(map: &'a mut Map) -> Result<$tx<&'a mut MapData>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $tx::<&'a mut MapData>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+
+            impl TryFrom<Map> for $tx<MapData> {
+                type Error = MapError;
+
+                fn try_from(map: Map) -> Result<$tx<MapData>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $tx::<MapData>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+       )+
+   }
+}
+
+impl_try_from_map!(
+    ProgramArray from Map::ProgramArray,
+    SockMap from Map::SockMap,
+    PerfEventArray from Map::PerfEventArray,
+    StackTraceMap from Map::StackTraceMap,
+);
+
+#[cfg(feature = "async")]
+#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
+impl_try_from_map!(
+    AsyncPerfEventArray from Map::PerfEventArray,
+);
+
+macro_rules! impl_try_from_map_generic_key_or_value {
+    ($($ty:ident),+ $(,)?) => {
+        $(
+            impl<'a, V:Pod> TryFrom<&'a Map> for $ty<&'a MapData, V> {
+                type Error = MapError;
+
+                fn try_from(map: &'a Map) -> Result<$ty<&'a MapData , V>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $ty::<&'a MapData,V>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+
+            impl<'a,V: Pod> TryFrom<&'a mut Map> for $ty<&'a mut MapData, V> {
+                type Error = MapError;
+
+                fn try_from(map: &'a mut Map) -> Result<$ty<&'a mut MapData, V>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $ty::<&'a mut MapData,V>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+
+            impl<V: Pod> TryFrom<Map> for $ty<MapData, V> {
+                type Error = MapError;
+
+                fn try_from(map: Map) -> Result<$ty<MapData, V>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $ty::<MapData,V>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+       )+
+   }
+}
+
+impl_try_from_map_generic_key_or_value!(Array, PerCpuArray, SockHash, BloomFilter, Queue, Stack,);
+
+macro_rules! impl_try_from_map_generic_key_and_value {
+    ($($ty:ident),+ $(,)?) => {
+        $(
+            impl<'a, V: Pod, K: Pod> TryFrom<&'a Map> for $ty<&'a MapData, V, K> {
+                type Error = MapError;
+
+                fn try_from(map: &'a Map) -> Result<$ty<&'a MapData,V,K>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $ty::<&'a MapData,V,K>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                    }
+                }
+            }
+
+            impl<'a,V: Pod,K: Pod> TryFrom<&'a mut Map> for $ty<&'a mut MapData, V, K> {
+                type Error = MapError;
+
+                fn try_from(map: &'a mut Map) -> Result<$ty<&'a mut MapData, V, K>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $ty::<&'a mut MapData,V,K>::new(m)
+                        },
+                        _ => Err(MapError::UnexpectedMapType),
+                }
+            }
+            }
+       )+
+   }
+}
+
+impl_try_from_map_generic_key_and_value!(HashMap, PerCpuHashMap, LpmTrie);
+
 /// A generic handle to a BPF map.
 ///
 /// You should never need to use this unless you're implementing a new map type.
-#[derive(Debug)]
-pub struct Map {
+#[derive(Debug, Clone)]
+pub struct MapData {
     pub(crate) obj: obj::Map,
     pub(crate) fd: Option<RawFd>,
     pub(crate) btf_fd: Option<RawFd>,
@@ -255,7 +420,19 @@ pub struct Map {
     pub pinned: bool,
 }
 
-impl Map {
+impl AsRef<MapData> for MapData {
+    fn as_ref(&self) -> &MapData {
+        self
+    }
+}
+
+impl AsMut<MapData> for MapData {
+    fn as_mut(&mut self) -> &mut MapData {
+        self
+    }
+}
+
+impl MapData {
     /// Creates a new map with the provided `name`
     pub fn create(&mut self, name: &str) -> Result<RawFd, MapError> {
         if self.fd.is_some() {
@@ -303,7 +480,7 @@ impl Map {
     }
 
     /// Loads a map from a pinned path in bpffs.
-    pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<Map, MapError> {
+    pub fn from_pin<P: AsRef<Path>>(path: P) -> Result<MapData, MapError> {
         let path_string =
             CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| {
                 MapError::PinError {
@@ -324,7 +501,7 @@ impl Map {
             io_error,
         })?;
 
-        Ok(Map {
+        Ok(MapData {
             obj: parse_map_info(info, PinningType::ByName),
             fd: Some(fd),
             btf_fd: None,
@@ -337,13 +514,13 @@ impl Map {
     /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`].
     /// This API is intended for cases where you have received a valid BPF FD from some other means.
     /// For example, you received an FD over Unix Domain Socket.
-    pub fn from_fd(fd: RawFd) -> Result<Map, MapError> {
+    pub fn from_fd(fd: RawFd) -> Result<MapData, MapError> {
         let info = bpf_map_get_info_by_fd(fd).map_err(|io_error| MapError::SyscallError {
             call: "BPF_OBJ_GET".to_owned(),
             io_error,
         })?;
 
-        Ok(Map {
+        Ok(MapData {
             obj: parse_map_info(info, PinningType::None),
             fd: Some(fd),
             btf_fd: None,
@@ -389,7 +566,7 @@ impl Map {
     }
 }
 
-impl Drop for Map {
+impl Drop for MapData {
     fn drop(&mut self) {
         // TODO: Replace this with an OwnedFd once that is stabilized.
         if let Some(fd) = self.fd.take() {
@@ -401,7 +578,7 @@ impl Drop for Map {
 /// An iterable map
 pub trait IterableMap<K: Pod, V> {
     /// Get a generic map handle
-    fn map(&self) -> &Map;
+    fn map(&self) -> &MapData;
 
     /// Get the value for the provided `key`
     fn get(&self, key: &K) -> Result<V, MapError>;
@@ -409,13 +586,13 @@ pub trait IterableMap<K: Pod, V> {
 
 /// Iterator returned by `map.keys()`.
 pub struct MapKeys<'coll, K: Pod> {
-    map: &'coll Map,
+    map: &'coll MapData,
     err: bool,
     key: Option<K>,
 }
 
 impl<'coll, K: Pod> MapKeys<'coll, K> {
-    fn new(map: &'coll Map) -> MapKeys<'coll, K> {
+    fn new(map: &'coll MapData) -> MapKeys<'coll, K> {
         MapKeys {
             map,
             err: false,
@@ -643,6 +820,7 @@ mod tests {
     use crate::{
         bpf_map_def,
         generated::{bpf_cmd, bpf_map_type::BPF_MAP_TYPE_HASH},
+        maps::MapData,
         obj::MapKind,
         sys::{override_syscall, Syscall},
     };
@@ -665,8 +843,8 @@ mod tests {
         })
     }
 
-    fn new_map() -> Map {
-        Map {
+    fn new_map() -> MapData {
+        MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,

+ 11 - 19
aya/src/maps/perf/async_perf_event_array.rs

@@ -1,6 +1,6 @@
 use bytes::BytesMut;
 use std::{
-    ops::DerefMut,
+    convert::AsMut,
     os::unix::prelude::{AsRawFd, RawFd},
 };
 
@@ -12,7 +12,7 @@ use tokio::io::unix::AsyncFd;
 
 use crate::maps::{
     perf::{Events, PerfBufferError, PerfEventArray, PerfEventArrayBuffer},
-    Map, MapError, MapRefMut,
+    MapData, MapError,
 };
 
 /// A `Future` based map that can be used to receive events from eBPF programs using the linux
@@ -45,7 +45,7 @@ use crate::maps::{
 /// # }
 /// # #[cfg(feature = "async_tokio")]
 /// # async fn try_main() -> Result<(), Error> {
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::perf::{AsyncPerfEventArray, PerfBufferError};
 /// use aya::util::online_cpus;
 /// use futures::future;
@@ -53,7 +53,7 @@ use crate::maps::{
 /// use tokio::task; // or async_std::task
 ///
 /// // try to convert the PERF_ARRAY map to an AsyncPerfEventArray
-/// let mut perf_array = AsyncPerfEventArray::try_from(bpf.map_mut("PERF_ARRAY")?)?;
+/// let mut perf_array: AsyncPerfEventArray<_> =bpf.take_map("PERF_ARRAY")?.try_into()?;
 ///
 /// for cpu_id in online_cpus()? {
 ///     // open a separate perf buffer for each cpu
@@ -85,11 +85,11 @@ use crate::maps::{
 /// # }
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_PERF_EVENT_ARRAY")]
-pub struct AsyncPerfEventArray<T: DerefMut<Target = Map>> {
+pub struct AsyncPerfEventArray<T> {
     perf_map: PerfEventArray<T>,
 }
 
-impl<T: DerefMut<Target = Map>> AsyncPerfEventArray<T> {
+impl<T: AsMut<MapData> + AsRef<MapData>> AsyncPerfEventArray<T> {
     /// Opens the perf buffer at the given index.
     ///
     /// The returned buffer will receive all the events eBPF programs send at the given index.
@@ -112,8 +112,8 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArray<T> {
     }
 }
 
-impl<T: DerefMut<Target = Map>> AsyncPerfEventArray<T> {
-    fn new(map: T) -> Result<AsyncPerfEventArray<T>, MapError> {
+impl<T: AsRef<MapData>> AsyncPerfEventArray<T> {
+    pub(crate) fn new(map: T) -> Result<AsyncPerfEventArray<T>, MapError> {
         Ok(AsyncPerfEventArray {
             perf_map: PerfEventArray::new(map)?,
         })
@@ -127,7 +127,7 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArray<T> {
 ///
 /// See the [`AsyncPerfEventArray` documentation](AsyncPerfEventArray) for an overview of how to
 /// use perf buffers.
-pub struct AsyncPerfEventArrayBuffer<T: DerefMut<Target = Map>> {
+pub struct AsyncPerfEventArrayBuffer<T> {
     buf: PerfEventArrayBuffer<T>,
 
     #[cfg(feature = "async_tokio")]
@@ -138,7 +138,7 @@ pub struct AsyncPerfEventArrayBuffer<T: DerefMut<Target = Map>> {
 }
 
 #[cfg(any(feature = "async_tokio"))]
-impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
+impl<T: AsMut<MapData> + AsRef<MapData>> AsyncPerfEventArrayBuffer<T> {
     /// Reads events from the buffer.
     ///
     /// This method reads events into the provided slice of buffers, filling
@@ -168,7 +168,7 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
 }
 
 #[cfg(all(not(feature = "async_tokio"), feature = "async_std"))]
-impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
+impl<T: AsMut<MapData> + AsRef<MapData>> AsyncPerfEventArrayBuffer<T> {
     /// Reads events from the buffer.
     ///
     /// This method reads events into the provided slice of buffers, filling
@@ -195,11 +195,3 @@ impl<T: DerefMut<Target = Map>> AsyncPerfEventArrayBuffer<T> {
         }
     }
 }
-
-impl TryFrom<MapRefMut> for AsyncPerfEventArray<MapRefMut> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<AsyncPerfEventArray<MapRefMut>, MapError> {
-        AsyncPerfEventArray::new(a)
-    }
-}

+ 19 - 28
aya/src/maps/perf/perf_event_array.rs

@@ -2,7 +2,8 @@
 //!
 //! [`perf`]: https://perf.wiki.kernel.org/index.php/Main_Page.
 use std::{
-    ops::DerefMut,
+    convert::AsMut,
+    ops::Deref,
     os::unix::io::{AsRawFd, RawFd},
     sync::Arc,
 };
@@ -10,10 +11,9 @@ use std::{
 use bytes::BytesMut;
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY,
     maps::{
         perf::{Events, PerfBuffer, PerfBufferError},
-        Map, MapError, MapRefMut,
+        MapData, MapError,
     },
     sys::bpf_map_update_elem,
     util::page_size,
@@ -26,12 +26,12 @@ use crate::{
 ///
 /// See the [`PerfEventArray` documentation](PerfEventArray) for an overview of how to use
 /// perf buffers.
-pub struct PerfEventArrayBuffer<T: DerefMut<Target = Map>> {
+pub struct PerfEventArrayBuffer<T> {
     _map: Arc<T>,
     buf: PerfBuffer,
 }
 
-impl<T: DerefMut<Target = Map>> PerfEventArrayBuffer<T> {
+impl<T: AsMut<MapData> + AsRef<MapData>> PerfEventArrayBuffer<T> {
     /// Returns true if the buffer contains events that haven't been read.
     pub fn readable(&self) -> bool {
         self.buf.readable()
@@ -55,7 +55,7 @@ impl<T: DerefMut<Target = Map>> PerfEventArrayBuffer<T> {
     }
 }
 
-impl<T: DerefMut<Target = Map>> AsRawFd for PerfEventArrayBuffer<T> {
+impl<T: AsMut<MapData> + AsRef<MapData>> AsRawFd for PerfEventArrayBuffer<T> {
     fn as_raw_fd(&self) -> RawFd {
         self.buf.as_raw_fd()
     }
@@ -83,15 +83,15 @@ impl<T: DerefMut<Target = Map>> AsRawFd for PerfEventArrayBuffer<T> {
 ///
 /// ```no_run
 /// # use aya::maps::perf::PerfEventArrayBuffer;
-/// # use aya::maps::Map;
-/// # use std::ops::DerefMut;
+/// # use aya::maps::MapData;
+/// # use std::convert::AsMut;
 /// # struct Poll<T> { _t: std::marker::PhantomData<T> };
-/// # impl<T: DerefMut<Target=Map>> Poll<T> {
+/// # impl<T: AsMut<MapData>> Poll<T> {
 /// #    fn poll_readable(&self) -> &mut [PerfEventArrayBuffer<T>] {
 /// #        &mut []
 /// #    }
 /// # }
-/// # fn poll_buffers<T: DerefMut<Target=Map>>(bufs: Vec<PerfEventArrayBuffer<T>>) -> Poll<T> {
+/// # fn poll_buffers<T: AsMut<MapData>>(bufs: Vec<PerfEventArrayBuffer<T>>) -> Poll<T> {
 /// #    Poll { _t: std::marker::PhantomData }
 /// # }
 /// # #[derive(thiserror::Error, Debug)]
@@ -105,12 +105,12 @@ impl<T: DerefMut<Target = Map>> AsRawFd for PerfEventArrayBuffer<T> {
 /// #    #[error(transparent)]
 /// #    PerfBuf(#[from] aya::maps::perf::PerfBufferError),
 /// # }
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::PerfEventArray;
 /// use aya::util::online_cpus;
 /// use bytes::BytesMut;
 ///
-/// let mut perf_array = PerfEventArray::try_from(bpf.map_mut("EVENTS")?)?;
+/// let mut perf_array: PerfEventArray<_> = bpf.map_mut("EVENTS")?.try_into()?;
 ///
 /// // eBPF programs are going to write to the EVENTS perf array, using the id of the CPU they're
 /// // running on as the array index.
@@ -155,25 +155,23 @@ impl<T: DerefMut<Target = Map>> AsRawFd for PerfEventArrayBuffer<T> {
 /// [tokio]: https://docs.rs/tokio
 /// [async-std]: https://docs.rs/async-std
 #[doc(alias = "BPF_MAP_TYPE_PERF_EVENT_ARRAY")]
-pub struct PerfEventArray<T: DerefMut<Target = Map>> {
+pub struct PerfEventArray<T> {
     map: Arc<T>,
     page_size: usize,
 }
 
-impl<T: DerefMut<Target = Map>> PerfEventArray<T> {
+impl<T: AsRef<MapData>> PerfEventArray<T> {
     pub(crate) fn new(map: T) -> Result<PerfEventArray<T>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
-        let _fd = map.fd_or_err()?;
+        let _fd = map.as_ref().fd_or_err()?;
 
         Ok(PerfEventArray {
             map: Arc::new(map),
             page_size: page_size(),
         })
     }
+}
 
+impl<T: AsMut<MapData> + AsRef<MapData>> PerfEventArray<T> {
     /// Opens the perf buffer at the given index.
     ///
     /// The returned buffer will receive all the events eBPF programs send at the given index.
@@ -185,7 +183,8 @@ impl<T: DerefMut<Target = Map>> PerfEventArray<T> {
         // FIXME: keep track of open buffers
 
         // this cannot fail as new() checks that the fd is open
-        let map_fd = self.map.fd_or_err().unwrap();
+        let map_data: &MapData = self.map.deref().as_ref();
+        let map_fd = map_data.fd_or_err().unwrap();
         let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?;
         bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0)
             .map_err(|(_, io_error)| io_error)?;
@@ -196,11 +195,3 @@ impl<T: DerefMut<Target = Map>> PerfEventArray<T> {
         })
     }
 }
-
-impl TryFrom<MapRefMut> for PerfEventArray<MapRefMut> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<PerfEventArray<MapRefMut>, MapError> {
-        PerfEventArray::new(a)
-    }
-}

+ 15 - 35
aya/src/maps/queue.rs

@@ -1,13 +1,12 @@
 //! A FIFO queue.
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
     mem,
-    ops::{Deref, DerefMut},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_QUEUE,
-    maps::{Map, MapError, MapRef, MapRefMut},
+    maps::{MapData, MapError},
     sys::{bpf_map_lookup_and_delete_elem, bpf_map_push_elem},
     Pod,
 };
@@ -20,39 +19,36 @@ use crate::{
 ///
 /// # Examples
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::Queue;
 ///
-/// let mut queue = Queue::try_from(bpf.map_mut("ARRAY")?)?;
+/// let mut queue: Queue<_, u32> = bpf.map_mut("ARRAY")?.try_into()?;
 /// queue.push(42, 0)?;
 /// queue.push(43, 0)?;
 /// assert_eq!(queue.pop(0)?, 42);
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_QUEUE")]
-pub struct Queue<T: Deref<Target = Map>, V: Pod> {
+pub struct Queue<T, V: Pod> {
     inner: T,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, V: Pod> Queue<T, V> {
-    fn new(map: T) -> Result<Queue<T, V>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_QUEUE as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>, V: Pod> Queue<T, V> {
+    pub(crate) fn new(map: T) -> Result<Queue<T, V>, MapError> {
+        let data = map.as_ref();
         let expected = 0;
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
 
         let expected = mem::size_of::<V>();
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(Queue {
             inner: map,
@@ -64,11 +60,11 @@ impl<T: Deref<Target = Map>, V: Pod> Queue<T, V> {
     ///
     /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
     pub fn capacity(&self) -> u32 {
-        self.inner.obj.max_entries()
+        self.inner.as_ref().obj.max_entries()
     }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
+impl<T: AsMut<MapData>, V: Pod> Queue<T, V> {
     /// Removes the first element and returns it.
     ///
     /// # Errors
@@ -76,7 +72,7 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
     /// Returns [`MapError::ElementNotFound`] if the queue is empty, [`MapError::SyscallError`]
     /// if `bpf_map_lookup_and_delete_elem` fails.
     pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_mut().fd_or_err()?;
 
         let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
             |(_, io_error)| MapError::SyscallError {
@@ -93,7 +89,7 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
     ///
     /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
     pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_mut().fd_or_err()?;
         bpf_map_push_elem(fd, &value, flags).map_err(|(_, io_error)| MapError::SyscallError {
             call: "bpf_map_push_elem".to_owned(),
             io_error,
@@ -101,19 +97,3 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Queue<T, V> {
         Ok(())
     }
 }
-
-impl<V: Pod> TryFrom<MapRef> for Queue<MapRef, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<Queue<MapRef, V>, MapError> {
-        Queue::new(a)
-    }
-}
-
-impl<V: Pod> TryFrom<MapRefMut> for Queue<MapRefMut, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<Queue<MapRefMut, V>, MapError> {
-        Queue::new(a)
-    }
-}

+ 18 - 42
aya/src/maps/sock/sock_hash.rs

@@ -1,14 +1,11 @@
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
-    ops::{Deref, DerefMut},
     os::unix::io::{AsRawFd, RawFd},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_SOCKHASH,
-    maps::{
-        hash_map, sock::SocketMap, IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut,
-    },
+    maps::{hash_map, sock::SocketMap, IterableMap, MapData, MapError, MapIter, MapKeys},
     sys::bpf_map_lookup_elem,
     Pod,
 };
@@ -47,7 +44,7 @@ use crate::{
 /// use aya::maps::SockHash;
 /// use aya::programs::SkMsg;
 ///
-/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
+/// let mut intercept_egress: SockHash<_, u32> = bpf.take_map("INTERCEPT_EGRESS")?.try_into()?;
 /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 /// prog.load()?;
 /// prog.attach(&intercept_egress)?;
@@ -60,21 +57,16 @@ use crate::{
 /// # Ok::<(), Error>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
-pub struct SockHash<T: Deref<Target = Map>, K> {
+pub struct SockHash<T, K> {
     inner: T,
     _k: PhantomData<K>,
 }
 
-impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
+impl<T: AsRef<MapData>, K: Pod> SockHash<T, K> {
     pub(crate) fn new(map: T) -> Result<SockHash<T, K>, MapError> {
-        let map_type = map.obj.map_type();
-
-        // validate the map definition
-        if map_type != BPF_MAP_TYPE_SOCKHASH as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
-        hash_map::check_kv_size::<K, u32>(&map)?;
-        let _ = map.fd_or_err()?;
+        let data = map.as_ref();
+        hash_map::check_kv_size::<K, u32>(data)?;
+        let _ = data.fd_or_err()?;
 
         Ok(SockHash {
             inner: map,
@@ -84,7 +76,7 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
 
     /// Returns the fd of the socket stored at the given key.
     pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
-        let fd = self.inner.deref().fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_lookup_elem".to_owned(),
@@ -103,25 +95,25 @@ impl<T: Deref<Target = Map>, K: Pod> SockHash<T, K> {
     /// An iterator visiting all keys in arbitrary order. The iterator element
     /// type is `Result<K, MapError>`.
     pub fn keys(&self) -> MapKeys<'_, K> {
-        MapKeys::new(&self.inner)
+        MapKeys::new(self.inner.as_ref())
     }
 }
 
-impl<T: DerefMut<Target = Map>, K: Pod> SockHash<T, K> {
+impl<T: AsMut<MapData>, K: Pod> SockHash<T, K> {
     /// Inserts a socket under the given key.
     pub fn insert<I: AsRawFd>(&mut self, key: K, value: I, flags: u64) -> Result<(), MapError> {
-        hash_map::insert(&mut self.inner, key, value.as_raw_fd(), flags)
+        hash_map::insert(self.inner.as_mut(), key, value.as_raw_fd(), flags)
     }
 
     /// Removes a socket from the map.
     pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
-        hash_map::remove(&mut self.inner, key)
+        hash_map::remove(self.inner.as_mut(), key)
     }
 }
 
-impl<T: Deref<Target = Map>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> {
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, key: &K) -> Result<RawFd, MapError> {
@@ -129,24 +121,8 @@ impl<T: Deref<Target = Map>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> {
     }
 }
 
-impl<T: DerefMut<Target = Map>, K: Pod> SocketMap for SockHash<T, K> {
+impl<T: AsRef<MapData>, K: Pod> SocketMap for SockHash<T, K> {
     fn fd_or_err(&self) -> Result<RawFd, MapError> {
-        self.inner.fd_or_err()
-    }
-}
-
-impl<K: Pod> TryFrom<MapRef> for SockHash<MapRef, K> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<SockHash<MapRef, K>, MapError> {
-        SockHash::new(a)
-    }
-}
-
-impl<K: Pod> TryFrom<MapRefMut> for SockHash<MapRefMut, K> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<SockHash<MapRefMut, K>, MapError> {
-        SockHash::new(a)
+        self.inner.as_ref().fd_or_err()
     }
 }

+ 18 - 38
aya/src/maps/sock/sock_map.rs

@@ -1,14 +1,13 @@
 //! An array of eBPF program file descriptors used as a jump table.
 
 use std::{
+    convert::{AsMut, AsRef},
     mem,
-    ops::{Deref, DerefMut},
     os::unix::{io::AsRawFd, prelude::RawFd},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_SOCKMAP,
-    maps::{sock::SocketMap, Map, MapError, MapKeys, MapRef, MapRefMut},
+    maps::{sock::SocketMap, MapData, MapError, MapKeys},
     sys::{bpf_map_delete_elem, bpf_map_update_elem},
 };
 
@@ -32,35 +31,32 @@ use crate::{
 /// use aya::maps::SockMap;
 /// use aya::programs::SkSkb;
 ///
-/// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?;
+/// let intercept_ingress: SockMap<_> = bpf.take_map("INTERCEPT_INGRESS")?.try_into()?;
 /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
 /// prog.load()?;
 /// prog.attach(&intercept_ingress)?;
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_SOCKMAP")]
-pub struct SockMap<T: Deref<Target = Map>> {
+pub struct SockMap<T: AsRef<MapData>> {
     pub(crate) inner: T,
 }
 
-impl<T: Deref<Target = Map>> SockMap<T> {
-    fn new(map: T) -> Result<SockMap<T>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_SOCKMAP as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>> SockMap<T> {
+    pub(crate) fn new(map: T) -> Result<SockMap<T>, MapError> {
+        let data = map.as_ref();
         let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
 
         let expected = mem::size_of::<RawFd>();
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(SockMap { inner: map })
     }
@@ -68,12 +64,12 @@ impl<T: Deref<Target = Map>> SockMap<T> {
     /// An iterator over the indices of the array that point to a program. The iterator item type
     /// is `Result<u32, MapError>`.
     pub fn indices(&self) -> MapKeys<'_, u32> {
-        MapKeys::new(&self.inner)
+        MapKeys::new(self.inner.as_ref())
     }
 
     fn check_bounds(&self, index: u32) -> Result<(), MapError> {
-        let max_entries = self.inner.obj.max_entries();
-        if index >= self.inner.obj.max_entries() {
+        let max_entries = self.inner.as_ref().obj.max_entries();
+        if index >= self.inner.as_ref().obj.max_entries() {
             Err(MapError::OutOfBounds { index, max_entries })
         } else {
             Ok(())
@@ -81,10 +77,10 @@ impl<T: Deref<Target = Map>> SockMap<T> {
     }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
+impl<T: AsRef<MapData> + AsMut<MapData>> SockMap<T> {
     /// Stores a socket into the map.
     pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         self.check_bounds(index)?;
         bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
             |(_, io_error)| MapError::SyscallError {
@@ -97,7 +93,7 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
 
     /// Removes the socket stored at `index` from the map.
     pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
         self.check_bounds(*index)?;
         bpf_map_delete_elem(fd, index)
             .map(|_| ())
@@ -108,24 +104,8 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
     }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SocketMap for SockMap<T> {
+impl<T: AsRef<MapData> + AsMut<MapData>> SocketMap for SockMap<T> {
     fn fd_or_err(&self) -> Result<RawFd, MapError> {
-        self.inner.fd_or_err()
-    }
-}
-
-impl TryFrom<MapRef> for SockMap<MapRef> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<SockMap<MapRef>, MapError> {
-        SockMap::new(a)
-    }
-}
-
-impl TryFrom<MapRefMut> for SockMap<MapRefMut> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<SockMap<MapRefMut>, MapError> {
-        SockMap::new(a)
+        self.inner.as_ref().fd_or_err()
     }
 }

+ 15 - 35
aya/src/maps/stack.rs

@@ -1,13 +1,12 @@
 //! A LIFO stack.
 use std::{
+    convert::{AsMut, AsRef},
     marker::PhantomData,
     mem,
-    ops::{Deref, DerefMut},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_STACK,
-    maps::{Map, MapError, MapRef, MapRefMut},
+    maps::{MapData, MapError},
     sys::{bpf_map_lookup_and_delete_elem, bpf_map_update_elem},
     Pod,
 };
@@ -20,39 +19,36 @@ use crate::{
 ///
 /// # Examples
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::Stack;
 ///
-/// let mut stack = Stack::try_from(bpf.map_mut("STACK")?)?;
+/// let mut stack: Stack<_, u32> = bpf.map_mut("STACK")?.try_into()?;
 /// stack.push(42, 0)?;
 /// stack.push(43, 0)?;
 /// assert_eq!(stack.pop(0)?, 43);
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_STACK")]
-pub struct Stack<T: Deref<Target = Map>, V: Pod> {
+pub struct Stack<T, V: Pod> {
     inner: T,
     _v: PhantomData<V>,
 }
 
-impl<T: Deref<Target = Map>, V: Pod> Stack<T, V> {
-    fn new(map: T) -> Result<Stack<T, V>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_STACK as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>, V: Pod> Stack<T, V> {
+    pub(crate) fn new(map: T) -> Result<Stack<T, V>, MapError> {
+        let data = map.as_ref();
         let expected = 0;
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
 
         let expected = mem::size_of::<V>();
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size != expected {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(Stack {
             inner: map,
@@ -64,11 +60,11 @@ impl<T: Deref<Target = Map>, V: Pod> Stack<T, V> {
     ///
     /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side.
     pub fn capacity(&self) -> u32 {
-        self.inner.obj.max_entries()
+        self.inner.as_ref().obj.max_entries()
     }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
+impl<T: AsMut<MapData>, V: Pod> Stack<T, V> {
     /// Removes the last element and returns it.
     ///
     /// # Errors
@@ -76,7 +72,7 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
     /// Returns [`MapError::ElementNotFound`] if the stack is empty, [`MapError::SyscallError`]
     /// if `bpf_map_lookup_and_delete_elem` fails.
     pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_mut().fd_or_err()?;
 
         let value = bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(
             |(_, io_error)| MapError::SyscallError {
@@ -93,7 +89,7 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
     ///
     /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails.
     pub fn push(&mut self, value: V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_mut().fd_or_err()?;
         bpf_map_update_elem(fd, None::<&u32>, &value, flags).map_err(|(_, io_error)| {
             MapError::SyscallError {
                 call: "bpf_map_update_elem".to_owned(),
@@ -103,19 +99,3 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>, V: Pod> Stack<T, V> {
         Ok(())
     }
 }
-
-impl<V: Pod> TryFrom<MapRef> for Stack<MapRef, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<Stack<MapRef, V>, MapError> {
-        Stack::new(a)
-    }
-}
-
-impl<V: Pod> TryFrom<MapRefMut> for Stack<MapRefMut, V> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<Stack<MapRefMut, V>, MapError> {
-        Stack::new(a)
-    }
-}

+ 14 - 34
aya/src/maps/stack_trace.rs

@@ -1,11 +1,10 @@
 //! A hash map of kernel or user space stack traces.
 //!
 //! See [`StackTraceMap`] for documentation and examples.
-use std::{collections::BTreeMap, fs, io, mem, ops::Deref, path::Path, str::FromStr};
+use std::{collections::BTreeMap, convert::AsRef, fs, io, mem, path::Path, str::FromStr};
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_STACK_TRACE,
-    maps::{IterableMap, Map, MapError, MapIter, MapKeys, MapRef, MapRefMut},
+    maps::{IterableMap, MapData, MapError, MapIter, MapKeys},
     sys::bpf_map_lookup_elem_ptr,
 };
 
@@ -68,14 +67,11 @@ pub struct StackTraceMap<T> {
     max_stack_depth: usize,
 }
 
-impl<T: Deref<Target = Map>> StackTraceMap<T> {
-    fn new(map: T) -> Result<StackTraceMap<T>, MapError> {
-        let map_type = map.obj.map_type();
-        if map_type != BPF_MAP_TYPE_STACK_TRACE as u32 {
-            return Err(MapError::InvalidMapType { map_type });
-        }
+impl<T: AsRef<MapData>> StackTraceMap<T> {
+    pub(crate) fn new(map: T) -> Result<StackTraceMap<T>, MapError> {
+        let data = map.as_ref();
         let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
+        let size = data.obj.key_size() as usize;
         if size != expected {
             return Err(MapError::InvalidKeySize { size, expected });
         }
@@ -87,11 +83,11 @@ impl<T: Deref<Target = Map>> StackTraceMap<T> {
                     io_error,
                 }
             })?;
-        let size = map.obj.value_size() as usize;
+        let size = data.obj.value_size() as usize;
         if size > max_stack_depth * mem::size_of::<u64>() {
             return Err(MapError::InvalidValueSize { size, expected });
         }
-        let _fd = map.fd_or_err()?;
+        let _fd = data.fd_or_err()?;
 
         Ok(StackTraceMap {
             inner: map,
@@ -106,7 +102,7 @@ impl<T: Deref<Target = Map>> StackTraceMap<T> {
     /// Returns [`MapError::KeyNotFound`] if there is no stack trace with the
     /// given `stack_id`, or [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails.
     pub fn get(&self, stack_id: &u32, flags: u64) -> Result<StackTrace, MapError> {
-        let fd = self.inner.fd_or_err()?;
+        let fd = self.inner.as_ref().fd_or_err()?;
 
         let mut frames = vec![0; self.max_stack_depth];
         bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags)
@@ -140,13 +136,13 @@ impl<T: Deref<Target = Map>> StackTraceMap<T> {
     /// An iterator visiting all the stack_ids in arbitrary order. The iterator element
     /// type is `Result<u32, MapError>`.
     pub fn stack_ids(&self) -> MapKeys<'_, u32> {
-        MapKeys::new(&self.inner)
+        MapKeys::new(self.inner.as_ref())
     }
 }
 
-impl<T: Deref<Target = Map>> IterableMap<u32, StackTrace> for StackTraceMap<T> {
-    fn map(&self) -> &Map {
-        &self.inner
+impl<T: AsRef<MapData>> IterableMap<u32, StackTrace> for StackTraceMap<T> {
+    fn map(&self) -> &MapData {
+        self.inner.as_ref()
     }
 
     fn get(&self, index: &u32) -> Result<StackTrace, MapError> {
@@ -154,23 +150,7 @@ impl<T: Deref<Target = Map>> IterableMap<u32, StackTrace> for StackTraceMap<T> {
     }
 }
 
-impl TryFrom<MapRef> for StackTraceMap<MapRef> {
-    type Error = MapError;
-
-    fn try_from(a: MapRef) -> Result<StackTraceMap<MapRef>, MapError> {
-        StackTraceMap::new(a)
-    }
-}
-
-impl TryFrom<MapRefMut> for StackTraceMap<MapRefMut> {
-    type Error = MapError;
-
-    fn try_from(a: MapRefMut) -> Result<StackTraceMap<MapRefMut>, MapError> {
-        StackTraceMap::new(a)
-    }
-}
-
-impl<'a, T: Deref<Target = Map>> IntoIterator for &'a StackTraceMap<T> {
+impl<'a, T: AsRef<MapData>> IntoIterator for &'a StackTraceMap<T> {
     type Item = Result<(u32, StackTrace), MapError>;
     type IntoIter = MapIter<'a, u32, StackTrace, StackTraceMap<T>>;
 

+ 9 - 8
aya/src/obj/relocation.rs

@@ -9,7 +9,7 @@ use crate::{
         bpf_insn, BPF_CALL, BPF_JMP, BPF_K, BPF_PSEUDO_CALL, BPF_PSEUDO_FUNC, BPF_PSEUDO_MAP_FD,
         BPF_PSEUDO_MAP_VALUE,
     },
-    maps::Map,
+    maps::MapData,
     obj::{Function, Object, Program},
     BpfError,
 };
@@ -62,7 +62,7 @@ pub(crate) struct Symbol {
 }
 
 impl Object {
-    pub fn relocate_maps(&mut self, maps: &HashMap<String, Map>) -> Result<(), BpfError> {
+    pub fn relocate_maps(&mut self, maps: &HashMap<String, MapData>) -> Result<(), BpfError> {
         let maps_by_section = maps
             .iter()
             .map(|(name, map)| (map.obj.section_index(), (name.as_str(), map)))
@@ -122,8 +122,8 @@ impl Object {
 fn relocate_maps<'a, I: Iterator<Item = &'a Relocation>>(
     fun: &mut Function,
     relocations: I,
-    maps_by_section: &HashMap<usize, (&str, &Map)>,
-    maps_by_symbol: &HashMap<usize, (&str, &Map)>,
+    maps_by_section: &HashMap<usize, (&str, &MapData)>,
+    maps_by_symbol: &HashMap<usize, (&str, &MapData)>,
     symbol_table: &HashMap<usize, Symbol>,
     text_section_index: Option<usize>,
 ) -> Result<(), RelocationError> {
@@ -438,6 +438,7 @@ fn insn_is_call(ins: &bpf_insn) -> bool {
 mod test {
     use crate::{
         bpf_map_def,
+        maps::MapData,
         obj::{self, BtfMap, LegacyMap, MapKind},
         BtfMapDef,
     };
@@ -460,8 +461,8 @@ mod test {
         unsafe { std::ptr::read_unaligned(bytes.as_ptr() as *const _) }
     }
 
-    fn fake_legacy_map(fd: i32, symbol_index: usize) -> Map {
-        Map {
+    fn fake_legacy_map(fd: i32, symbol_index: usize) -> MapData {
+        MapData {
             obj: obj::Map::Legacy(LegacyMap {
                 def: bpf_map_def {
                     ..Default::default()
@@ -477,8 +478,8 @@ mod test {
         }
     }
 
-    fn fake_btf_map(fd: i32, symbol_index: usize) -> Map {
-        Map {
+    fn fake_btf_map(fd: i32, symbol_index: usize) -> MapData {
+        MapData {
             obj: obj::Map::Btf(BtfMap {
                 def: BtfMapDef {
                     ..Default::default()

+ 1 - 1
aya/src/programs/sk_msg.rs

@@ -40,7 +40,7 @@ use crate::{
 /// use aya::maps::SockHash;
 /// use aya::programs::SkMsg;
 ///
-/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
+/// let mut intercept_egress: SockHash<_, u32> = bpf.take_map("INTERCEPT_EGRESS")?.try_into()?;
 /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 /// prog.load()?;
 /// prog.attach(&intercept_egress)?;

+ 1 - 1
aya/src/programs/sk_skb.rs

@@ -38,7 +38,7 @@ pub enum SkSkbKind {
 /// use aya::maps::SockMap;
 /// use aya::programs::SkSkb;
 ///
-/// let intercept_ingress = SockMap::try_from(bpf.map_mut("INTERCEPT_INGRESS")?)?;
+/// let intercept_ingress: SockMap<_> = bpf.take_map("INTERCEPT_INGRESS")?.try_into()?;
 /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
 /// prog.load()?;
 /// prog.attach(&intercept_ingress)?;

+ 3 - 3
test/integration-test/src/tests/load.rs

@@ -2,7 +2,7 @@ use std::{process::Command, thread, time};
 
 use aya::{
     include_bytes_aligned,
-    maps::{Array, MapRefMut},
+    maps::Array,
     programs::{
         links::{FdLink, PinnedLink},
         TracePoint, Xdp, XdpFlags,
@@ -36,8 +36,8 @@ fn multiple_btf_maps() -> anyhow::Result<()> {
         include_bytes_aligned!("../../../../target/bpfel-unknown-none/debug/multimap-btf.bpf.o");
     let mut bpf = Bpf::load(bytes)?;
 
-    let map_1: Array<MapRefMut, u64> = Array::try_from(bpf.map_mut("map_1")?)?;
-    let map_2: Array<MapRefMut, u64> = Array::try_from(bpf.map_mut("map_2")?)?;
+    let map_1: Array<_, u64> = bpf.take_map("map_1")?.try_into()?;
+    let map_2: Array<_, u64> = bpf.take_map("map_2")?.try_into()?;
 
     let prog: &mut TracePoint = bpf.program_mut("tracepoint").unwrap().try_into().unwrap();
     prog.load().unwrap();