Browse Source

aya: Use PinError for all pinning errors

Signed-off-by: Dave Tucker <[email protected]>
Dave Tucker 2 years ago
parent
commit
34ba2bc048
6 changed files with 98 additions and 83 deletions
  1. 12 2
      aya/src/bpf.rs
  2. 1 0
      aya/src/lib.rs
  3. 25 31
      aya/src/maps/mod.rs
  4. 35 0
      aya/src/pin.rs
  5. 8 25
      aya/src/programs/links.rs
  6. 17 25
      aya/src/programs/mod.rs

+ 12 - 2
aya/src/bpf.rs

@@ -400,7 +400,10 @@ impl<'a> BpfLoader<'a> {
                         }
                         Err(_) => {
                             let fd = map.create(&name)?;
-                            map.pin(&name, path)?;
+                            map.pin(&name, path).map_err(|error| MapError::PinError {
+                                name: name.to_string(),
+                                error,
+                            })?;
                             fd
                         }
                     }
@@ -774,12 +777,19 @@ impl Bpf {
     /// # Examples
     /// ```no_run
     /// # use std::path::Path;
+    /// # #[derive(thiserror::Error, Debug)]
+    /// # enum Error {
+    /// #     #[error(transparent)]
+    /// #     Bpf(#[from] aya::BpfError),
+    /// #     #[error(transparent)]
+    /// #     Pin(#[from] aya::pin::PinError)
+    /// # }
     /// # let mut bpf = aya::Bpf::load(&[])?;
     /// # let pin_path = Path::new("/tmp/pin_path");
     /// for (_, program) in bpf.programs_mut() {
     ///     program.pin(pin_path)?;
     /// }
-    /// # Ok::<(), aya::BpfError>(())
+    /// # Ok::<(), Error>(())
     /// ```
     pub fn programs_mut(&mut self) -> impl Iterator<Item = (&str, &mut Program)> {
         self.programs.iter_mut().map(|(s, p)| (s.as_str(), p))

+ 1 - 0
aya/src/lib.rs

@@ -48,6 +48,7 @@ mod bpf;
 mod generated;
 pub mod maps;
 mod obj;
+pub mod pin;
 pub mod programs;
 mod sys;
 pub mod util;

+ 25 - 31
aya/src/maps/mod.rs

@@ -51,6 +51,7 @@ use thiserror::Error;
 use crate::{
     generated::bpf_map_type,
     obj,
+    pin::PinError,
     sys::{bpf_create_map, bpf_get_object, bpf_map_get_next_key, bpf_pin_object, kernel_version},
     util::nr_cpus,
     Pod,
@@ -119,13 +120,6 @@ pub enum MapError {
         name: String,
     },
 
-    /// The map has already been pinned
-    #[error("the map `{name}` has already been pinned")]
-    AlreadyPinned {
-        /// Map name
-        name: String,
-    },
-
     /// Failed to create map
     #[error("failed to create map `{name}` with code {code}")]
     CreateError {
@@ -138,18 +132,6 @@ pub enum MapError {
         io_error: io::Error,
     },
 
-    /// Failed to pin map
-    #[error("failed to pin map `{name}` with code {code}")]
-    PinError {
-        /// Map Name
-        name: String,
-        /// Error code
-        code: libc::c_long,
-        #[source]
-        /// Original io::Error
-        io_error: io::Error,
-    },
-
     /// Invalid key size
     #[error("invalid key size {size}, expected {expected}")]
     InvalidKeySize {
@@ -214,6 +196,16 @@ pub enum MapError {
         /// Map name
         name: String,
     },
+
+    /// Could not pin map by name
+    #[error("map `{name}` requested pinning by name. pinning failed")]
+    PinError {
+        /// The map name
+        name: String,
+        /// The reason for the failure
+        #[source]
+        error: PinError,
+    },
 }
 
 /// A map file descriptor.
@@ -316,11 +308,12 @@ impl Map {
                 })
             }
         };
-        let fd = bpf_get_object(&path_string).map_err(|(code, io_error)| MapError::PinError {
-            name: name.into(),
-            code,
-            io_error,
-        })? as RawFd;
+        let fd =
+            bpf_get_object(&path_string).map_err(|(code, io_error)| MapError::SyscallError {
+                call: "BPF_OBJ_GET".to_string(),
+                code,
+                io_error,
+            })? as RawFd;
 
         self.fd = Some(fd);
 
@@ -336,20 +329,21 @@ impl Map {
         self.fd.ok_or(MapError::NotCreated)
     }
 
-    pub(crate) fn pin<P: AsRef<Path>>(&mut self, name: &str, path: P) -> Result<(), MapError> {
+    pub(crate) fn pin<P: AsRef<Path>>(&mut self, name: &str, path: P) -> Result<(), PinError> {
         if self.pinned {
-            return Err(MapError::AlreadyPinned { name: name.into() });
+            return Err(PinError::AlreadyPinned { name: name.into() });
         }
         let map_path = path.as_ref().join(name);
-        let fd = self.fd_or_err()?;
+        let fd = self.fd.ok_or(PinError::NoFd {
+            name: name.to_string(),
+        })?;
         let path_string = CString::new(map_path.to_string_lossy().into_owned()).map_err(|e| {
-            MapError::InvalidPinPath {
+            PinError::InvalidPinPath {
                 error: e.to_string(),
             }
         })?;
-        bpf_pin_object(fd, &path_string).map_err(|(code, io_error)| MapError::SyscallError {
-            call: "BPF_OBJ_PIN".to_string(),
-            code,
+        bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
+            name: "BPF_OBJ_GET".to_string(),
             io_error,
         })?;
         self.pinned = true;

+ 35 - 0
aya/src/pin.rs

@@ -0,0 +1,35 @@
+//! Pinning BPF objects to the BPF filesystem.
+use std::io;
+use thiserror::Error;
+
+/// An error ocurred working with a pinned BPF object.
+#[derive(Error, Debug)]
+pub enum PinError {
+    /// The object has already been pinned.
+    #[error("the BPF object `{name}` has already been pinned")]
+    AlreadyPinned {
+        /// Object name.
+        name: String,
+    },
+    /// The object FD is not known by Aya.
+    #[error("the BPF object `{name}`'s FD is not known")]
+    NoFd {
+        /// Object name.
+        name: String,
+    },
+    /// The path for the BPF object is not valid.
+    #[error("invalid pin path `{error}`")]
+    InvalidPinPath {
+        /// The error message.
+        error: String,
+    },
+    /// An error ocurred making a syscall.
+    #[error("{name} failed")]
+    SyscallError {
+        /// The syscall name.
+        name: String,
+        /// The [`io::Error`] returned by the syscall.
+        #[source]
+        io_error: io::Error,
+    },
+}

+ 8 - 25
aya/src/programs/links.rs

@@ -1,12 +1,10 @@
 //! Program links.
 use libc::{close, dup};
-use thiserror::Error;
 
 use std::{
     borrow::Borrow,
     collections::{hash_map::Entry, HashMap},
     ffi::CString,
-    io,
     ops::Deref,
     os::unix::prelude::RawFd,
     path::Path,
@@ -14,28 +12,11 @@ use std::{
 
 use crate::{
     generated::bpf_attach_type,
+    pin::PinError,
     programs::ProgramError,
     sys::{bpf_pin_object, bpf_prog_detach},
 };
 
-/// An error ocurred working with a Link.
-#[derive(Error, Debug)]
-pub enum LinkError {
-    /// Invalid Pin Path.
-    #[error("invalid pin path `{error}`")]
-    InvalidPinPath {
-        /// The error message.
-        error: String,
-    },
-    /// Pinning error.
-    #[error("BPF_OBJ_PIN failed")]
-    PinError {
-        /// The [`io::Error`] returned by the syscall.
-        #[source]
-        io_error: io::Error,
-    },
-}
-
 /// A Link.
 pub trait Link: std::fmt::Debug + 'static {
     /// Unique Id
@@ -142,17 +123,19 @@ impl FdLink {
     ///
     /// When a BPF object is pinned to a BPF filesystem it will remain attached after
     /// Aya has detached the link.
-    /// To remove the attachment, the file on the BPF filesystem must be remove.
+    /// To remove the attachment, the file on the BPF filesystem must be removed.
     /// Any directories in the the path provided should have been created by the caller.
-    pub fn pin<P: AsRef<Path>>(&self, path: P) -> Result<(), LinkError> {
+    pub fn pin<P: AsRef<Path>>(&self, path: P) -> Result<(), PinError> {
         let path_string =
             CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| {
-                LinkError::InvalidPinPath {
+                PinError::InvalidPinPath {
                     error: e.to_string(),
                 }
             })?;
-        bpf_pin_object(self.fd, &path_string)
-            .map_err(|(_code, io_error)| LinkError::PinError { io_error })?;
+        bpf_pin_object(self.fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
+            name: "BPF_OBJ_PIN".to_string(),
+            io_error,
+        })?;
         Ok(())
     }
 }

+ 17 - 25
aya/src/programs/mod.rs

@@ -106,6 +106,7 @@ use crate::{
     generated::{bpf_attach_type, bpf_prog_info, bpf_prog_type},
     maps::MapError,
     obj::{self, btf::BtfError, Function, KernelVersion},
+    pin::PinError,
     sys::{
         bpf_get_object, bpf_load_program, bpf_obj_get_info_by_fd, bpf_pin_object,
         bpf_prog_get_fd_by_id, bpf_prog_query, retry_with_verifier_logs, BpfLoadProgramAttrs,
@@ -163,13 +164,6 @@ pub enum ProgramError {
     #[error("unexpected program type")]
     UnexpectedProgramType,
 
-    /// Invalid pin path
-    #[error("invalid pin path `{error}`")]
-    InvalidPinPath {
-        /// the error message
-        error: String,
-    },
-
     /// A map error occurred while loading or attaching a program.
     #[error(transparent)]
     MapError(#[from] MapError),
@@ -307,7 +301,7 @@ impl Program {
     }
 
     /// Pin the program to the provided path
-    pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), ProgramError> {
+    pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError> {
         match self {
             Program::KProbe(p) => p.pin(path),
             Program::UProbe(p) => p.pin(path),
@@ -458,15 +452,21 @@ fn unload_program<T: Link>(data: &mut ProgramData<T>) -> Result<(), ProgramError
 fn pin_program<T: Link, P: AsRef<Path>>(
     data: &mut ProgramData<T>,
     path: P,
-) -> Result<(), ProgramError> {
-    let fd = data.fd_or_err()?;
+) -> Result<(), PinError> {
+    let fd = data.fd.ok_or(PinError::NoFd {
+        name: data
+            .name
+            .as_ref()
+            .unwrap_or(&"<unknown program>".to_string())
+            .to_string(),
+    })?;
     let path_string = CString::new(path.as_ref().to_string_lossy().into_owned()).map_err(|e| {
-        ProgramError::InvalidPinPath {
+        PinError::InvalidPinPath {
             error: e.to_string(),
         }
     })?;
-    bpf_pin_object(fd, &path_string).map_err(|(_code, io_error)| ProgramError::SyscallError {
-        call: "BPF_OBJ_PIN".to_string(),
+    bpf_pin_object(fd, &path_string).map_err(|(_, io_error)| PinError::SyscallError {
+        name: "BPF_OBJ_PIN".to_string(),
         io_error,
     })?;
     Ok(())
@@ -681,9 +681,9 @@ macro_rules! impl_program_pin{
                 ///
                 /// When a BPF object is pinned to a BPF filesystem it will remain loaded after
                 /// Aya has unloaded the program.
-                /// To remove the program, the file on the BPF filesystem must be remove.
+                /// To remove the program, the file on the BPF filesystem must be removed.
                 /// Any directories in the the path provided should have been created by the caller.
-                pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), ProgramError> {
+                pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError> {
                     pin_program(&mut self.data, path)
                 }
             }
@@ -814,17 +814,10 @@ impl ProgramInfo {
 
     /// Loads a program from a pinned path in bpffs.
     pub fn from_pinned<P: AsRef<Path>>(path: P) -> Result<ProgramInfo, ProgramError> {
-        let path_string = match CString::new(path.as_ref().to_str().unwrap()) {
-            Ok(s) => s,
-            Err(e) => {
-                return Err(ProgramError::InvalidPinPath {
-                    error: e.to_string(),
-                })
-            }
-        };
+        let path_string = CString::new(path.as_ref().to_str().unwrap()).unwrap();
         let fd =
             bpf_get_object(&path_string).map_err(|(_, io_error)| ProgramError::SyscallError {
-                call: "bpf_obj_get".to_owned(),
+                call: "BPF_OBJ_GET".to_owned(),
                 io_error,
             })? as RawFd;
 
@@ -832,7 +825,6 @@ impl ProgramInfo {
             call: "bpf_obj_get_info_by_fd".to_owned(),
             io_error,
         })?;
-
         unsafe {
             libc::close(fd);
         }