Browse Source

maps: move maps inside RefCells

Alessandro Decina 4 years ago
parent
commit
f7cdd2e059
3 changed files with 63 additions and 27 deletions
  1. 10 7
      src/bpf.rs
  2. 33 11
      src/maps/hash_map.rs
  3. 20 9
      src/maps/perf_map.rs

+ 10 - 7
src/bpf.rs

@@ -1,4 +1,7 @@
-use std::collections::HashMap;
+use std::{
+    cell::{Ref, RefCell, RefMut},
+    collections::HashMap,
+};
 
 use thiserror::Error;
 
@@ -45,7 +48,7 @@ unsafe impl object::Pod for bpf_map_def {}
 
 #[derive(Debug)]
 pub struct Bpf {
-    maps: HashMap<String, Map>,
+    maps: HashMap<String, RefCell<Map>>,
     programs: HashMap<String, Program>,
 }
 
@@ -91,18 +94,18 @@ impl Bpf {
         Ok(Bpf {
             maps: maps
                 .drain(..)
-                .map(|map| (map.obj.name.clone(), map))
+                .map(|map| (map.obj.name.clone(), RefCell::new(map)))
                 .collect(),
             programs,
         })
     }
 
-    pub fn map(&self, name: &str) -> Option<&Map> {
-        self.maps.get(name)
+    pub fn map(&self, name: &str) -> Option<Ref<'_, Map>> {
+        self.maps.get(name).map(|cell| cell.borrow())
     }
 
-    pub fn map_mut(&mut self, name: &str) -> Option<&mut Map> {
-        self.maps.get_mut(name)
+    pub fn map_mut(&self, name: &str) -> Option<RefMut<'_, Map>> {
+        self.maps.get(name).map(|cell| cell.borrow_mut())
     }
 
     pub fn program(&self, name: &str) -> Option<&Program> {

+ 33 - 11
src/maps/hash_map.rs

@@ -1,4 +1,10 @@
-use std::{convert::TryFrom, marker::PhantomData, mem};
+use std::{
+    cell::{Ref, RefMut},
+    convert::TryFrom,
+    marker::PhantomData,
+    mem,
+    ops::{Deref, DerefMut},
+};
 
 use crate::{
     generated::bpf_map_type::BPF_MAP_TYPE_HASH,
@@ -10,15 +16,15 @@ use crate::{
     Pod, RawFd,
 };
 
-pub struct HashMap<T: AsRef<Map>, K, V> {
+pub struct HashMap<T: Deref<Target = Map>, K, V> {
     inner: T,
     _k: PhantomData<K>,
     _v: PhantomData<V>,
 }
 
-impl<T: AsRef<Map>, K: Pod, V: Pod> HashMap<T, K, V> {
+impl<T: Deref<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
     pub fn new(map: T) -> Result<HashMap<T, K, V>, MapError> {
-        let inner = map.as_ref();
+        let inner = map.deref();
         let map_type = inner.obj.def.map_type;
         if map_type != BPF_MAP_TYPE_HASH {
             return Err(MapError::InvalidMapType {
@@ -45,7 +51,7 @@ impl<T: AsRef<Map>, K: Pod, V: Pod> HashMap<T, K, V> {
     }
 
     pub unsafe fn get(&self, key: &K, flags: u64) -> Result<Option<V>, MapError> {
-        let fd = self.inner.as_ref().fd_or_err()?;
+        let fd = self.inner.deref().fd_or_err()?;
         bpf_map_lookup_elem(fd, key, flags)
             .map_err(|(code, io_error)| MapError::LookupElementFailed { code, io_error })
     }
@@ -59,31 +65,31 @@ impl<T: AsRef<Map>, K: Pod, V: Pod> HashMap<T, K, V> {
     }
 }
 
-impl<T: AsRef<Map> + AsMut<Map>, K: Pod, V: Pod> HashMap<T, K, V> {
+impl<T: DerefMut<Target = Map>, K: Pod, V: Pod> HashMap<T, K, V> {
     pub fn insert(&mut self, key: K, value: V, flags: u64) -> Result<(), MapError> {
-        let fd = self.inner.as_ref().fd_or_err()?;
+        let fd = self.inner.deref_mut().fd_or_err()?;
         bpf_map_update_elem(fd, &key, &value, flags)
             .map_err(|(code, io_error)| MapError::UpdateElementFailed { code, io_error })?;
         Ok(())
     }
 
     pub unsafe fn pop(&mut self, key: &K) -> Result<Option<V>, MapError> {
-        let fd = self.inner.as_ref().fd_or_err()?;
+        let fd = self.inner.deref_mut().fd_or_err()?;
         bpf_map_lookup_and_delete_elem(fd, key)
             .map_err(|(code, io_error)| MapError::LookupAndDeleteElementFailed { code, io_error })
     }
 
     pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
-        let fd = self.inner.as_ref().fd_or_err()?;
+        let fd = self.inner.deref_mut().fd_or_err()?;
         bpf_map_delete_elem(fd, key)
             .map(|_| ())
             .map_err(|(code, io_error)| MapError::DeleteElementFailed { code, io_error })
     }
 }
 
-impl<T: AsRef<Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
+impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
     fn fd(&self) -> Result<RawFd, MapError> {
-        self.inner.as_ref().fd_or_err()
+        self.inner.deref().fd_or_err()
     }
 
     unsafe fn get(&self, key: &K) -> Result<Option<V>, MapError> {
@@ -91,6 +97,22 @@ impl<T: AsRef<Map>, K: Pod, V: Pod> IterableMap<K, V> for HashMap<T, K, V> {
     }
 }
 
+impl<'a, K: Pod, V: Pod> TryFrom<Ref<'a, Map>> for HashMap<Ref<'a, Map>, K, V> {
+    type Error = MapError;
+
+    fn try_from(inner: Ref<'a, Map>) -> Result<HashMap<Ref<'a, Map>, K, V>, MapError> {
+        HashMap::new(inner)
+    }
+}
+
+impl<'a, K: Pod, V: Pod> TryFrom<RefMut<'a, Map>> for HashMap<RefMut<'a, Map>, K, V> {
+    type Error = MapError;
+
+    fn try_from(inner: RefMut<'a, Map>) -> Result<HashMap<RefMut<'a, Map>, K, V>, MapError> {
+        HashMap::new(inner)
+    }
+}
+
 impl<'a, K: Pod, V: Pod> TryFrom<&'a Map> for HashMap<&'a Map, K, V> {
     type Error = MapError;
 

+ 20 - 9
src/maps/perf_map.rs

@@ -1,7 +1,10 @@
 use std::{
+    cell::RefMut,
     convert::TryFrom,
     ffi::c_void,
-    fs, io, mem, ptr, slice,
+    fs, io, mem,
+    ops::DerefMut,
+    ptr, slice,
     str::FromStr,
     sync::atomic::{self, AtomicPtr, Ordering},
 };
@@ -277,18 +280,18 @@ pub enum PerfMapError {
     },
 }
 
-pub struct PerfMap<'map> {
-    map: &'map Map,
+pub struct PerfMap<T: DerefMut<Target = Map>> {
+    map: T,
     cpu_fds: Vec<(u32, RawFd)>,
     buffers: Vec<Option<PerfBuffer>>,
 }
 
-impl<'map> PerfMap<'map> {
+impl<T: DerefMut<Target = Map>> PerfMap<T> {
     pub fn new(
-        map: &'map Map,
+        map: T,
         cpu_ids: Option<Vec<u32>>,
         page_count: Option<usize>,
-    ) -> Result<PerfMap<'map>, PerfMapError> {
+    ) -> Result<PerfMap<T>, PerfMapError> {
         let map_type = map.obj.def.map_type;
         if map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY {
             return Err(MapError::InvalidMapType {
@@ -345,11 +348,19 @@ impl<'map> PerfMap<'map> {
     }
 }
 
-impl<'inner> TryFrom<&'inner Map> for PerfMap<'inner> {
+impl<'a> TryFrom<RefMut<'a, Map>> for PerfMap<RefMut<'a, Map>> {
     type Error = PerfMapError;
 
-    fn try_from(inner: &'inner Map) -> Result<PerfMap<'inner>, PerfMapError> {
-        PerfMap::new(inner, None, None)
+    fn try_from(a: RefMut<'a, Map>) -> Result<PerfMap<RefMut<'a, Map>>, PerfMapError> {
+        PerfMap::new(a, None, None)
+    }
+}
+
+impl<'a> TryFrom<&'a mut Map> for PerfMap<&'a mut Map> {
+    type Error = PerfMapError;
+
+    fn try_from(a: &'a mut Map) -> Result<PerfMap<&'a mut Map>, PerfMapError> {
+        PerfMap::new(a, None, None)
     }
 }