Browse Source

Merge pull request #397 from astoycos/refactor-map-api2

Refactor map API
Alessandro Decina 2 years ago
parent
commit
d6cb1a1

+ 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").unwrap().try_into()?;
 
         for cpu_id in online_cpus().map_err(Error::InvalidOnlineCpu)? {
             let mut buf = logs.open(cpu_id, None)?;

+ 1 - 1
aya/Cargo.toml

@@ -34,4 +34,4 @@ async_std = ["async-io", "async"]
 
 [package.metadata.docs.rs]
 all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "docsrs","-D", "warnings"]

+ 60 - 51
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, 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,43 @@ 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 = bpf_map_type::try_from(map.obj.map_type())?;
+    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 | BPF_MAP_TYPE_LRU_PERCPU_HASH => {
+            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 +684,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>,
 }
 
@@ -714,22 +743,8 @@ impl Bpf {
     ///
     /// 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. 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(),
-                })
-            })
+    pub fn map(&self, name: &str) -> Option<&Map> {
+        self.maps.get(name)
     }
 
     /// Returns a mutable reference to the map with the given name.
@@ -739,22 +754,24 @@ impl Bpf {
     ///
     /// For more details and examples on maps and their usage, see the [maps module
     /// documentation][crate::maps].
+    pub fn map_mut(&mut self, name: &str) -> Option<&mut Map> {
+        self.maps.get_mut(name)
+    }
+
+    /// Takes ownership of a map with the given name.
     ///
-    /// # Errors
+    /// Use this when borrowing with [`map`](crate::Bpf::map) or [`map_mut`](crate::Bpf::map_mut)
+    /// is not possible (eg when using the map from an async task). The returned
+    /// map will be closed on `Drop`, therefore the caller is responsible for
+    /// managing its lifetime.
     ///
-    /// 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> {
-        self.maps
-            .get(name)
-            .ok_or_else(|| MapError::MapNotFound {
-                name: name.to_owned(),
-            })
-            .and_then(|lock| {
-                lock.try_write().map_err(|_| MapError::BorrowError {
-                    name: name.to_owned(),
-                })
-            })
+    /// 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].
+    pub fn take_map(&mut self, name: &str) -> Option<Map> {
+        self.maps.remove(name)
     }
 
     /// An iterator over all the maps.
@@ -764,22 +781,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, &Map)> {
+        self.maps.iter().map(|(name, map)| (name.as_str(), map))
     }
 
     /// Returns a reference to the program with the given name.

+ 21 - 58
aya/src/maps/array/array.rs

@@ -1,12 +1,10 @@
 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::{check_bounds, check_kv_size, IterableMap, MapData, MapError},
     sys::{bpf_map_lookup_elem, bpf_map_update_elem},
     Pod,
 };
@@ -22,38 +20,26 @@ 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::try_from(bpf.map_mut("ARRAY").unwrap())?;
 /// 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 });
-        }
-        let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidKeySize { size, expected });
-        }
+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();
+        check_kv_size::<u32, V>(data)?;
 
-        let expected = mem::size_of::<V>();
-        let size = map.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 +51,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 +61,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();
+        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 +79,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 +89,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();
+        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 +102,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)
-    }
-}

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

@@ -4,6 +4,6 @@ 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;

+ 22 - 58
aya/src/maps/array/per_cpu_array.rs

@@ -1,12 +1,10 @@
 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::{check_bounds, check_kv_size, IterableMap, MapData, MapError, PerCpuValues},
     sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
     Pod,
 };
@@ -31,11 +29,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::try_from(bpf.map_mut("ARRAY").unwrap())?;
 ///
 /// // set array[1] = 42 for all cpus
 /// let nr_cpus = nr_cpus()?;
@@ -50,29 +48,17 @@ 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 });
-        }
-        let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidKeySize { size, expected });
-        }
+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();
+        check_kv_size::<u32, V>(data)?;
 
-        let expected = mem::size_of::<V>();
-        let size = map.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 +70,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 +80,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();
+        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 +98,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 +108,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();
+        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 +122,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)
-    }
-}

+ 18 - 54
aya/src/maps/array/program_array.rs

@@ -1,14 +1,12 @@
 //! An array of eBPF program file descriptors used as a jump table.
 
 use std::{
-    mem,
-    ops::{Deref, DerefMut},
+    convert::{AsMut, AsRef},
     os::unix::prelude::{AsRawFd, RawFd},
 };
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_PROG_ARRAY,
-    maps::{Map, MapError, MapKeys, MapRef, MapRefMut},
+    maps::{check_bounds, check_kv_size, MapData, MapError, MapKeys},
     programs::ProgramFd,
     sys::{bpf_map_delete_elem, bpf_map_update_elem},
 };
@@ -29,7 +27,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::try_from(bpf.take_map("JUMP_TABLE").unwrap())?;
 /// 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 +47,16 @@ 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 });
-        }
-        let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidKeySize { size, expected });
-        }
+impl<T: AsRef<MapData>> ProgramArray<T> {
+    pub(crate) fn new(map: T) -> Result<ProgramArray<T>, MapError> {
+        let data = map.as_ref();
+        check_kv_size::<u32, RawFd>(data)?;
 
-        let expected = mem::size_of::<RawFd>();
-        let size = map.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 +64,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();
+        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 +93,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();
+        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 +105,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)
-    }
-}

+ 25 - 65
aya/src/maps/bloom_filter.rs

@@ -1,11 +1,8 @@
 //! A Bloom Filter.
-use std::{marker::PhantomData, ops::Deref};
-
-use core::mem;
+use std::{convert::AsRef, marker::PhantomData};
 
 use crate::{
-    generated::bpf_map_type::BPF_MAP_TYPE_BLOOM_FILTER,
-    maps::{Map, MapError, MapRef, MapRefMut},
+    maps::{check_v_size, MapData, MapError},
     sys::{bpf_map_lookup_elem_ptr, bpf_map_push_elem},
     Pod,
 };
@@ -19,10 +16,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::try_from(bpf.map_mut("BLOOM_FILTER").unwrap())?;
 ///
 /// bloom_filter.insert(1, 0)?;
 ///
@@ -33,27 +30,17 @@ 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 size = mem::size_of::<V>();
-        let expected = map.obj.value_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidValueSize { size, expected });
-        };
+        let data = map.as_ref();
+        check_v_size::<V>(data)?;
 
-        let _ = map.fd_or_err()?;
+        let _ = data.fd_or_err()?;
 
         Ok(BloomFilter {
             inner: map,
@@ -63,7 +50,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 +63,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 +72,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 +81,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 +110,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 +127,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,6 +146,8 @@ mod tests {
             btf_fd: None,
         };
 
+        let map = Map::PerfEventArray(map_data);
+
         assert!(matches!(
             BloomFilter::<_, u32>::try_from(&map),
             Err(MapError::InvalidMapType { .. })
@@ -198,7 +156,7 @@ mod tests {
 
     #[test]
     fn test_new_not_created() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -213,7 +171,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 +183,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 +198,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 +222,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 +236,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 +259,7 @@ mod tests {
             } => sys_error(ENOENT),
             _ => sys_error(EFAULT),
         });
-        let map = Map {
+        let map = MapData {
             obj: new_obj_map(),
             fd: Some(42),
             pinned: false,

+ 66 - 90
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::{check_kv_size, 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::try_from(bpf.map_mut("REDIRECT_PORTS").unwrap())?;
 ///
 /// // 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();
+        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::<_, u32, u32>::try_from(&map),
+            HashMap::<_, u8, u32>::try_from(&map),
             Err(MapError::InvalidMapType { .. })
         ));
     }
 
+    #[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, 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,

+ 9 - 18
aya/src/maps/hash_map/mod.rs

@@ -1,8 +1,6 @@
 //! Hash map types.
-use std::mem;
-
 use crate::{
-    maps::{Map, MapError},
+    maps::MapError,
     sys::{bpf_map_delete_elem, bpf_map_update_elem},
 };
 
@@ -13,21 +11,14 @@ 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> {
-    let size = mem::size_of::<K>();
-    let expected = map.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;
-    if size != expected {
-        return Err(MapError::InvalidValueSize { size, expected });
-    };
-    Ok(())
-}
+use super::MapData;
 
-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 +30,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(|_| ())

+ 19 - 60
aya/src/maps/hash_map/per_cpu_hash_map.rs

@@ -1,13 +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,
+        check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys, PerCpuValues,
     },
     sys::{bpf_map_lookup_elem_per_cpu, bpf_map_update_elem_per_cpu},
     Pod,
@@ -26,13 +25,13 @@ use crate::{
 /// # Examples
 ///
 /// ```no_run
-/// # let bpf = aya::Bpf::load(&[])?;
+/// # let mut bpf = aya::Bpf::load(&[])?;
 /// use aya::maps::PerCpuHashMap;
 ///
 /// const CPU_IDS: u8 = 1;
 /// const WAKEUPS: u8 = 2;
 ///
-/// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map("COUNTERS")?)?;
+/// let mut hm = PerCpuHashMap::<_, u8, u32>::try_from(bpf.map_mut("PER_CPU_STORAGE").unwrap())?;
 /// let cpu_ids = unsafe { hm.get(&CPU_IDS, 0)? };
 /// let wakeups = unsafe { hm.get(&WAKEUPS, 0)? };
 /// for (cpu_id, wakeups) in cpu_ids.iter().zip(wakeups.iter()) {
@@ -42,24 +41,18 @@ 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();
+        check_kv_size::<K, V>(data)?;
 
-        // validate the map definition
-        if map_type != BPF_MAP_TYPE_PERCPU_HASH as u32
-            && map_type != BPF_MAP_TYPE_LRU_PERCPU_HASH as u32
-        {
-            return Err(MapError::InvalidMapType { map_type });
-        }
-        hash_map::check_kv_size::<K, V>(&map)?;
-        let _ = map.fd_or_err()?;
+        let _ = data.fd_or_err()?;
 
         Ok(PerCpuHashMap {
             inner: map,
@@ -70,7 +63,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 +82,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 +101,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>::try_from(bpf.map_mut("PER_CPU_STORAGE").unwrap())?;
     /// hm.insert(
     ///     RETRIES,
     ///     PerCpuValues::try_from(vec![3u32; nr_cpus()?])?,
@@ -123,7 +116,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 +129,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)
-    }
-}

+ 44 - 80
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::{check_kv_size, 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::try_from(bpf.map_mut("LPM_TRIE").unwrap())?;
 /// 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,12 @@ 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 size = mem::size_of::<Key<K>>();
-        let expected = map.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;
-        if size != expected {
-            return Err(MapError::InvalidValueSize { size, expected });
-        };
+        let data = map.as_ref();
+        check_kv_size::<Key<K>, V>(data)?;
 
-        let _ = map.fd_or_err()?;
+        let _ = data.fd_or_err()?;
 
         Ok(LpmTrie {
             inner: map,
@@ -126,7 +115,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 +124,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 +143,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 +154,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 +165,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 +174,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 +203,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 +220,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 +237,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,6 +256,8 @@ mod tests {
             pinned: false,
         };
 
+        let map = Map::PerfEventArray(map_data);
+
         assert!(matches!(
             LpmTrie::<_, u32, u32>::try_from(&map),
             Err(MapError::InvalidMapType { .. })
@@ -304,7 +266,7 @@ mod tests {
 
     #[test]
     fn test_new_not_created() {
-        let mut map = Map {
+        let mut map = MapData {
             obj: new_obj_map(),
             fd: None,
             pinned: false,
@@ -319,7 +281,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 +293,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 +308,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 +333,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 +350,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 +375,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 +390,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 +415,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
-    }
-}

+ 284 - 49
aya/src/maps/mod.rs

@@ -4,25 +4,30 @@
 //! 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), or [`Bpf::take_map`](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::take_map`](crate::Bpf::take_map) always return the
+//! opaque [`&Map`](crate::maps::Map), [`&mut Map`](crate::maps::Map), and [`Map`](crate::maps::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::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?;
+//! let map_fd = intercept_egress.fd()?;
 //! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 //! prog.load()?;
-//! prog.attach(&intercept_egress)?;
+//! prog.attach(map_fd)?;
+//!
 //! # Ok::<(), aya::BpfError>(())
 //! ```
 //!
@@ -32,6 +37,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 +64,6 @@ use crate::{
     PinningType, Pod,
 };
 
-mod map_lock;
-
 pub mod array;
 pub mod bloom_filter;
 pub mod hash_map;
@@ -71,8 +75,12 @@ 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(feature = "async")]
+#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
+pub use perf::AsyncPerfEventArray;
 pub use perf::PerfEventArray;
 pub use queue::Queue;
 pub use sock::{SockHash, SockMap};
@@ -82,13 +90,6 @@ pub use stack_trace::StackTraceMap;
 #[derive(Error, Debug)]
 /// Errors occuring from working with Maps
 pub enum MapError {
-    /// Unable to find the map
-    #[error("map `{name}` not found ")]
-    MapNotFound {
-        /// Map name
-        name: String,
-    },
-
     /// Invalid map type encontered
     #[error("invalid map type {map_type}")]
     InvalidMapType {
@@ -174,20 +175,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 {
@@ -243,11 +230,234 @@ 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 [`StackTraceMap`] map
+    StackTraceMap(MapData),
+    /// A [`Queue`] map
+    Queue(MapData),
+}
+
+impl Map {
+    /// Returns the low level map type.
+    fn map_type(&self) -> u32 {
+        match self {
+            Map::Array(map) => map.obj.map_type(),
+            Map::PerCpuArray(map) => map.obj.map_type(),
+            Map::ProgramArray(map) => map.obj.map_type(),
+            Map::HashMap(map) => map.obj.map_type(),
+            Map::PerCpuHashMap(map) => map.obj.map_type(),
+            Map::PerfEventArray(map) => map.obj.map_type(),
+            Map::SockHash(map) => map.obj.map_type(),
+            Map::SockMap(map) => map.obj.map_type(),
+            Map::BloomFilter(map) => map.obj.map_type(),
+            Map::LpmTrie(map) => map.obj.map_type(),
+            Map::Stack(map) => map.obj.map_type(),
+            Map::StackTraceMap(map) => map.obj.map_type(),
+            Map::Queue(map) => map.obj.map_type(),
+        }
+    }
+}
+
+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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+
+            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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+
+            impl TryFrom<Map> for $tx<MapData> {
+                type Error = MapError;
+
+                fn try_from(map: Map) -> Result<$tx<MapData>, MapError> {
+                    match map {
+                        Map::$ty(m) => {
+                            $tx::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+       )+
+   }
+}
+
+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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+
+            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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+
+            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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+       )+
+   }
+}
+
+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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                    }
+                }
+            }
+
+            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::new(m)
+                        },
+                        _ => Err(MapError::InvalidMapType{ map_type: map.map_type()}),
+                }
+            }
+            }
+       )+
+   }
+}
+
+impl_try_from_map_generic_key_and_value!(HashMap, PerCpuHashMap, LpmTrie);
+
+pub(crate) fn check_bounds(map: &MapData, index: u32) -> Result<(), MapError> {
+    let max_entries = map.obj.max_entries();
+    if index >= max_entries {
+        Err(MapError::OutOfBounds { index, max_entries })
+    } else {
+        Ok(())
+    }
+}
+
+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 {
+        return Err(MapError::InvalidKeySize { size, expected });
+    }
+    let size = mem::size_of::<V>();
+    let expected = map.obj.value_size() as usize;
+    if size != expected {
+        return Err(MapError::InvalidValueSize { size, expected });
+    };
+    Ok(())
+}
+
+pub(crate) fn check_v_size<V>(map: &MapData) -> Result<(), MapError> {
+    let size = mem::size_of::<V>();
+    let expected = map.obj.value_size() as usize;
+    if size != expected {
+        return Err(MapError::InvalidValueSize { size, expected });
+    };
+    Ok(())
+}
+
 /// 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 {
+pub struct MapData {
     pub(crate) obj: obj::Map,
     pub(crate) fd: Option<RawFd>,
     pub(crate) btf_fd: Option<RawFd>,
@@ -255,7 +465,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 +525,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 +546,7 @@ impl Map {
             io_error,
         })?;
 
-        Ok(Map {
+        Ok(MapData {
             obj: parse_map_info(info, PinningType::ByName),
             fd: Some(fd),
             btf_fd: None,
@@ -334,16 +556,16 @@ impl Map {
 
     /// Loads a map from a [`RawFd`].
     ///
-    /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`].
+    /// If loading from a BPF Filesystem (bpffs) you should use [`Map::from_pin`](crate::maps::MapData::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,
@@ -351,11 +573,6 @@ impl Map {
         })
     }
 
-    /// Returns the [`bpf_map_type`] of this map
-    pub fn map_type(&self) -> Result<bpf_map_type, MapError> {
-        bpf_map_type::try_from(self.obj.map_type())
-    }
-
     pub(crate) fn fd_or_err(&self) -> Result<RawFd, MapError> {
         self.fd.ok_or(MapError::NotCreated)
     }
@@ -389,7 +606,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() {
@@ -398,10 +615,26 @@ impl Drop for Map {
     }
 }
 
+impl Clone for MapData {
+    fn clone(&self) -> MapData {
+        MapData {
+            obj: self.obj.clone(),
+            fd: {
+                if let Some(fd) = self.fd {
+                    unsafe { Some(libc::dup(fd)) };
+                }
+                None
+            },
+            btf_fd: self.btf_fd,
+            pinned: self.pinned,
+        }
+    }
+}
+
 /// 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 +642,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,
@@ -538,6 +771,7 @@ impl TryFrom<u32> for bpf_map_type {
         })
     }
 }
+
 pub(crate) struct PerCpuKernelMem {
     bytes: Vec<u8>,
 }
@@ -643,6 +877,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 +900,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::try_from(bpf.take_map("PERF_ARRAY").unwrap())?;
 ///
 /// 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)
-    }
-}

+ 1 - 1
aya/src/maps/perf/mod.rs

@@ -1,6 +1,6 @@
 //! Ring buffer types used to receive events from eBPF programs using the linux `perf` API.
 //!
-//! See the [`PerfEventArray`] and [`AsyncPerfEventArray`].
+//! See the [`PerfEventArray`](crate::maps::PerfEventArray) and [`AsyncPerfEventArray`](crate::maps::perf::AsyncPerfEventArray).
 #[cfg(any(feature = "async"))]
 #[cfg_attr(docsrs, doc(cfg(feature = "async")))]
 mod async_perf_event_array;

+ 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::try_from(bpf.map_mut("EVENTS").unwrap())?;
 ///
 /// // 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)
-    }
-}

+ 14 - 44
aya/src/maps/queue.rs

@@ -1,13 +1,11 @@
 //! 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::{check_kv_size, MapData, MapError},
     sys::{bpf_map_lookup_and_delete_elem, bpf_map_push_elem},
     Pod,
 };
@@ -20,39 +18,27 @@ 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::try_from(bpf.map_mut("ARRAY").unwrap())?;
 /// 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 });
-        }
-        let expected = 0;
-        let size = map.obj.key_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidKeySize { size, expected });
-        }
+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();
+        check_kv_size::<(), V>(data)?;
 
-        let expected = mem::size_of::<V>();
-        let size = map.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 +50,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 +62,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 +79,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 +87,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)
-    }
-}

+ 10 - 8
aya/src/maps/sock/mod.rs

@@ -2,15 +2,17 @@
 mod sock_hash;
 mod sock_map;
 
-use std::os::unix::io::RawFd;
-
-use crate::maps::MapError;
-
 pub use sock_hash::SockHash;
 pub use sock_map::SockMap;
 
-/// Shared behaviour between [`SockHash`] and [`SockMap`]
-pub trait SocketMap {
-    /// Returns a [`Result`] containg the map fd or an error if there is none
-    fn fd_or_err(&self) -> Result<RawFd, MapError>;
+use std::os::unix::io::{AsRawFd, RawFd};
+
+/// A socket map file descriptor.
+#[derive(Copy, Clone)]
+pub struct SockMapFd(RawFd);
+
+impl AsRawFd for SockMapFd {
+    fn as_raw_fd(&self) -> RawFd {
+        self.0
+    }
 }

+ 29 - 45
aya/src/maps/sock/sock_hash.rs

@@ -1,13 +1,12 @@
 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,
+        check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapIter, MapKeys,
     },
     sys::bpf_map_lookup_elem,
     Pod,
@@ -47,12 +46,16 @@ 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>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?;
+/// let map_fd = intercept_egress.fd()?;
+///
 /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(&intercept_egress)?;
+/// prog.attach(map_fd)?;
 ///
 /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
+/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?;
+///
 /// intercept_egress.insert(1234, client.as_raw_fd(), 0)?;
 ///
 /// // the write will be intercepted
@@ -60,21 +63,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();
+        check_kv_size::<K, u32>(data)?;
+        let _ = data.fd_or_err()?;
 
         Ok(SockHash {
             inner: map,
@@ -84,7 +82,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,50 +101,36 @@ 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())
+    }
+
+    /// Returns the map's file descriptor.
+    ///
+    /// The returned file descriptor can be used to attach programs that work with
+    /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb).
+    pub fn fd(&self) -> Result<SockMapFd, MapError> {
+        Ok(SockMapFd(self.inner.as_ref().fd_or_err()?))
     }
 }
 
-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> {
         SockHash::get(self, key, 0)
     }
 }
-
-impl<T: DerefMut<Target = Map>, 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)
-    }
-}

+ 27 - 59
aya/src/maps/sock/sock_map.rs

@@ -1,14 +1,12 @@
 //! An array of eBPF program file descriptors used as a jump table.
 
 use std::{
-    mem,
-    ops::{Deref, DerefMut},
+    convert::{AsMut, AsRef},
     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::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapKeys},
     sys::{bpf_map_delete_elem, bpf_map_update_elem},
 };
 
@@ -32,35 +30,26 @@ 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::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?;
+/// let map_fd = intercept_ingress.fd()?;
+///
 /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(&intercept_ingress)?;
+/// prog.attach(map_fd)?;
+///
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 #[doc(alias = "BPF_MAP_TYPE_SOCKMAP")]
-pub struct SockMap<T: Deref<Target = Map>> {
+pub struct SockMap<T> {
     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 });
-        }
-        let expected = mem::size_of::<u32>();
-        let size = map.obj.key_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidKeySize { size, expected });
-        }
+impl<T: AsRef<MapData>> SockMap<T> {
+    pub(crate) fn new(map: T) -> Result<SockMap<T>, MapError> {
+        let data = map.as_ref();
+        check_kv_size::<u32, RawFd>(data)?;
 
-        let expected = mem::size_of::<RawFd>();
-        let size = map.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,24 +57,24 @@ 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() {
-            Err(MapError::OutOfBounds { index, max_entries })
-        } else {
-            Ok(())
-        }
+    /// Returns the map's file descriptor.
+    ///
+    /// The returned file descriptor can be used to attach programs that work with
+    /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb).
+    pub fn fd(&self) -> Result<SockMapFd, MapError> {
+        Ok(SockMapFd(self.inner.as_ref().fd_or_err()?))
     }
 }
 
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
+impl<T: 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()?;
-        self.check_bounds(index)?;
+        let data = self.inner.as_mut();
+        let fd = data.fd_or_err()?;
+        check_bounds(data, index)?;
         bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
             |(_, io_error)| MapError::SyscallError {
                 call: "bpf_map_update_elem".to_owned(),
@@ -97,8 +86,9 @@ 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()?;
-        self.check_bounds(*index)?;
+        let data = self.inner.as_mut();
+        let fd = data.fd_or_err()?;
+        check_bounds(data, *index)?;
         bpf_map_delete_elem(fd, index)
             .map(|_| ())
             .map_err(|(_, io_error)| MapError::SyscallError {
@@ -107,25 +97,3 @@ impl<T: Deref<Target = Map> + DerefMut<Target = Map>> SockMap<T> {
             })
     }
 }
-
-impl<T: Deref<Target = Map> + DerefMut<Target = Map>> 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)
-    }
-}

+ 14 - 44
aya/src/maps/stack.rs

@@ -1,13 +1,11 @@
 //! 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::{check_kv_size, MapData, MapError},
     sys::{bpf_map_lookup_and_delete_elem, bpf_map_update_elem},
     Pod,
 };
@@ -20,39 +18,27 @@ 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::try_from(bpf.map_mut("STACK").unwrap())?;
 /// 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 });
-        }
-        let expected = 0;
-        let size = map.obj.key_size() as usize;
-        if size != expected {
-            return Err(MapError::InvalidKeySize { size, expected });
-        }
+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();
+        check_kv_size::<(), V>(data)?;
 
-        let expected = mem::size_of::<V>();
-        let size = map.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 +50,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 +62,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 +79,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 +89,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)
-    }
-}

+ 15 - 35
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,
 };
 
@@ -36,7 +35,7 @@ use crate::{
 /// use aya::maps::StackTraceMap;
 /// use aya::util::kernel_symbols;
 ///
-/// let mut stack_traces = StackTraceMap::try_from(bpf.map("STACK_TRACES")?)?;
+/// let mut stack_traces = StackTraceMap::try_from(bpf.map("STACK_TRACES").unwrap())?;
 /// // load kernel symbols from /proc/kallsyms
 /// let ksyms = kernel_symbols()?;
 ///
@@ -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()

+ 12 - 5
aya/src/programs/sk_msg.rs

@@ -1,7 +1,10 @@
 //! Skmsg programs.
+
+use std::os::unix::io::AsRawFd;
+
 use crate::{
     generated::{bpf_attach_type::BPF_SK_MSG_VERDICT, bpf_prog_type::BPF_PROG_TYPE_SK_MSG},
-    maps::sock::SocketMap,
+    maps::sock::SockMapFd,
     programs::{
         define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData,
         ProgramError,
@@ -40,12 +43,16 @@ use crate::{
 /// use aya::maps::SockHash;
 /// use aya::programs::SkMsg;
 ///
-/// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS")?)?;
+/// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?;
+/// let map_fd = intercept_egress.fd()?;
+///
 /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(&intercept_egress)?;
+/// prog.attach(map_fd)?;
 ///
 /// let mut client = TcpStream::connect("127.0.0.1:1234")?;
+/// let mut intercept_egress: SockHash<_, u32> = bpf.map_mut("INTERCEPT_EGRESS").unwrap().try_into()?;
+///
 /// intercept_egress.insert(1234, client.as_raw_fd(), 0)?;
 ///
 /// // the write will be intercepted
@@ -71,9 +78,9 @@ impl SkMsg {
     /// Attaches the program to the given sockmap.
     ///
     /// The returned value can be used to detach, see [SkMsg::detach].
-    pub fn attach(&mut self, map: &dyn SocketMap) -> Result<SkMsgLinkId, ProgramError> {
+    pub fn attach(&mut self, map: SockMapFd) -> Result<SkMsgLinkId, ProgramError> {
         let prog_fd = self.data.fd_or_err()?;
-        let map_fd = map.fd_or_err()?;
+        let map_fd = map.as_raw_fd();
 
         bpf_prog_attach(prog_fd, map_fd, BPF_SK_MSG_VERDICT).map_err(|(_, io_error)| {
             ProgramError::SyscallError {

+ 11 - 5
aya/src/programs/sk_skb.rs

@@ -1,10 +1,13 @@
 //! Skskb programs.
+
+use std::os::unix::io::AsRawFd;
+
 use crate::{
     generated::{
         bpf_attach_type::{BPF_SK_SKB_STREAM_PARSER, BPF_SK_SKB_STREAM_VERDICT},
         bpf_prog_type::BPF_PROG_TYPE_SK_SKB,
     },
-    maps::sock::SocketMap,
+    maps::sock::SockMapFd,
     programs::{
         define_link_wrapper, load_program, ProgAttachLink, ProgAttachLinkId, ProgramData,
         ProgramError,
@@ -38,10 +41,13 @@ 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.map("INTERCEPT_INGRESS").unwrap().try_into()?;
+/// let map_fd = intercept_ingress.fd()?;
+///
 /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach(&intercept_ingress)?;
+/// prog.attach(map_fd)?;
+///
 /// # Ok::<(), aya::BpfError>(())
 /// ```
 ///
@@ -64,9 +70,9 @@ impl SkSkb {
     /// Attaches the program to the given socket map.
     ///
     /// The returned value can be used to detach, see [SkSkb::detach].
-    pub fn attach(&mut self, map: &dyn SocketMap) -> Result<SkSkbLinkId, ProgramError> {
+    pub fn attach(&mut self, map: SockMapFd) -> Result<SkSkbLinkId, ProgramError> {
         let prog_fd = self.data.fd_or_err()?;
-        let map_fd = map.fd_or_err()?;
+        let map_fd = map.as_raw_fd();
 
         let attach_type = match self.kind {
             SkSkbKind::StreamParser => BPF_SK_SKB_STREAM_PARSER,

+ 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").unwrap().try_into()?;
+    let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into()?;
 
     let prog: &mut TracePoint = bpf.program_mut("tracepoint").unwrap().try_into().unwrap();
     prog.load().unwrap();

+ 1 - 1
xtask/src/docs/mod.rs

@@ -68,7 +68,7 @@ fn build_docs(working_dir: &PathBuf, abs_header_path: &Path) -> Result<(), anyho
         .env(
             "RUSTDOCFLAGS",
             format!(
-                "--cfg docsrs --html-in-header {}",
+                "--cfg docsrs --html-in-header {} -D warnings",
                 abs_header_path.to_str().unwrap()
             ),
         )