rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ariel Miculas <amiculas@cisco.com>
To: rust-for-linux@vger.kernel.org
Cc: Ariel Miculas <amiculas@cisco.com>
Subject: [PATCH 48/80] samples: puzzlefs: add basic deserializing support for the puzzlefs metadata
Date: Fri,  9 Jun 2023 09:30:46 +0300	[thread overview]
Message-ID: <20230609063118.24852-49-amiculas@cisco.com> (raw)
In-Reply-To: <20230609063118.24852-1-amiculas@cisco.com>

Signed-off-by: Ariel Miculas <amiculas@cisco.com>
---
 samples/rust/puzzle.rs                    |   2 +
 samples/rust/puzzle/error.rs              |  32 +++
 samples/rust/puzzle/types.rs              | 304 ++++++++++++++++++++++
 samples/rust/puzzle/types/cbor_helpers.rs |   9 +
 samples/rust/puzzlefs.rs                  |   2 +
 5 files changed, 349 insertions(+)
 create mode 100644 samples/rust/puzzle.rs
 create mode 100644 samples/rust/puzzle/error.rs
 create mode 100644 samples/rust/puzzle/types.rs
 create mode 100644 samples/rust/puzzle/types/cbor_helpers.rs

diff --git a/samples/rust/puzzle.rs b/samples/rust/puzzle.rs
new file mode 100644
index 000000000000..4d558561974d
--- /dev/null
+++ b/samples/rust/puzzle.rs
@@ -0,0 +1,2 @@
+pub(crate) mod error;
+mod types;
diff --git a/samples/rust/puzzle/error.rs b/samples/rust/puzzle/error.rs
new file mode 100644
index 000000000000..3427c5d2f7e3
--- /dev/null
+++ b/samples/rust/puzzle/error.rs
@@ -0,0 +1,32 @@
+use core::fmt::{self, Display};
+
+// TODO use String in error types (when it's available from the kernel)
+
+pub(crate) enum WireFormatError {
+    LocalRefError,
+    SeekOtherError,
+    ValueMissing,
+    CBORError(serde_cbor::Error),
+}
+
+impl Display for WireFormatError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            WireFormatError::LocalRefError => f.write_str("cannot turn local ref into a digest"),
+            WireFormatError::SeekOtherError => f.write_str("cannot seek to other blob"),
+            WireFormatError::ValueMissing => f.write_str("no value present"),
+            WireFormatError::CBORError(_) => f.write_str("CBOR error"),
+        }
+    }
+}
+
+pub(crate) type Result<T> = kernel::error::Result<T, WireFormatError>;
+
+// TODO figure out how to use thiserror
+#[allow(unused_qualifications)]
+impl core::convert::From<serde_cbor::Error> for WireFormatError {
+    #[allow(deprecated)]
+    fn from(source: serde_cbor::Error) -> Self {
+        WireFormatError::CBORError(source)
+    }
+}
diff --git a/samples/rust/puzzle/types.rs b/samples/rust/puzzle/types.rs
new file mode 100644
index 000000000000..207e5c4f86fa
--- /dev/null
+++ b/samples/rust/puzzle/types.rs
@@ -0,0 +1,304 @@
+use crate::puzzle::error::WireFormatError;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::mem::size_of;
+use serde::de::Error as SerdeError;
+use serde::de::Visitor;
+use serde::{Deserialize, Deserializer};
+use serde_derive::Deserialize;
+mod cbor_helpers;
+use crate::puzzle::error::Result;
+pub(crate) use cbor_helpers::cbor_size_of_list_header;
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct InodeAdditional {
+    #[allow(dead_code)]
+    pub(crate) xattrs: Vec<Xattr>,
+    #[allow(dead_code)]
+    pub(crate) symlink_target: Option<Vec<u8>>,
+}
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct Xattr {
+    #[allow(dead_code)]
+    pub(crate) key: Vec<u8>,
+    #[allow(dead_code)]
+    pub(crate) val: Vec<u8>,
+}
+
+pub(crate) struct MetadataBlob {
+    mmapped_region: Box<[u8]>,
+    inode_count: usize,
+}
+
+fn read_one_from_slice<'a, T: Deserialize<'a>>(bytes: &'a [u8]) -> Result<T> {
+    // serde complains when we leave extra bytes on the wire, which we often want to do. as a
+    // hack, we create a streaming deserializer for the type we're about to read, and then only
+    // read one value.
+    let mut iter = serde_cbor::Deserializer::from_slice(bytes).into_iter::<T>();
+    let v = iter.next().transpose()?;
+    v.ok_or(WireFormatError::ValueMissing)
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) enum BlobRefKind {
+    Local,
+    Other { digest: [u8; 32] },
+}
+
+const BLOB_REF_SIZE: usize = 1 /* mode */ + 32 /* digest */ + 8 /* offset */;
+
+// TODO: should this be an ociv1 digest and include size and media type?
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) struct BlobRef {
+    pub(crate) offset: u64,
+    pub(crate) kind: BlobRefKind,
+    pub(crate) compressed: bool,
+}
+
+const COMPRESSED_BIT: u8 = 1 << 7;
+
+impl BlobRef {
+    fn fixed_length_deserialize<E: SerdeError>(
+        state: &[u8; BLOB_REF_SIZE],
+    ) -> kernel::error::Result<BlobRef, E> {
+        let offset = u64::from_le_bytes(state[0..8].try_into().unwrap());
+
+        let compressed = (state[8] & COMPRESSED_BIT) != 0;
+        let kind = match state[8] & !COMPRESSED_BIT {
+            0 => BlobRefKind::Local,
+            1 => BlobRefKind::Other {
+                digest: state[9..41].try_into().unwrap(),
+            },
+            _ => {
+                return Err(SerdeError::custom(format_args!(
+                    "bad blob ref kind {}",
+                    state[0]
+                )))
+            }
+        };
+
+        Ok(BlobRef {
+            offset,
+            kind,
+            compressed,
+        })
+    }
+}
+
+impl<'de> Deserialize<'de> for BlobRef {
+    fn deserialize<D>(deserializer: D) -> kernel::error::Result<BlobRef, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        struct BlobRefVisitor;
+
+        impl<'de> Visitor<'de> for BlobRefVisitor {
+            type Value = BlobRef;
+
+            fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+                formatter.write_fmt(format_args!("expected {BLOB_REF_SIZE} bytes for BlobRef"))
+            }
+
+            fn visit_bytes<E>(self, v: &[u8]) -> kernel::error::Result<BlobRef, E>
+            where
+                E: SerdeError,
+            {
+                let state: [u8; BLOB_REF_SIZE] = v
+                    .try_into()
+                    .map_err(|_| SerdeError::invalid_length(v.len(), &self))?;
+                BlobRef::fixed_length_deserialize(&state)
+            }
+        }
+
+        deserializer.deserialize_bytes(BlobRefVisitor)
+    }
+}
+
+impl MetadataBlob {
+    pub(crate) fn seek_ref(&mut self, r: &BlobRef) -> Result<u64> {
+        match r.kind {
+            BlobRefKind::Other { .. } => Err(WireFormatError::SeekOtherError),
+            BlobRefKind::Local => Ok(r.offset),
+        }
+    }
+
+    pub(crate) fn read_file_chunks(&mut self, offset: u64) -> Result<Vec<FileChunk>> {
+        read_one_from_slice::<FileChunkList>(&self.mmapped_region[offset as usize..])
+            .map(|cl| cl.chunks)
+    }
+
+    pub(crate) fn read_dir_list(&mut self, offset: u64) -> Result<DirList> {
+        read_one_from_slice(&self.mmapped_region[offset as usize..])
+    }
+
+    pub(crate) fn read_inode_additional(&mut self, r: &BlobRef) -> Result<InodeAdditional> {
+        let offset = self.seek_ref(r)? as usize;
+        read_one_from_slice(&self.mmapped_region[offset..])
+    }
+
+    pub(crate) fn find_inode(&mut self, ino: Ino) -> Result<Option<Inode>> {
+        let mut left = 0;
+        let mut right = self.inode_count;
+
+        while left <= right {
+            let mid = left + (right - left) / 2;
+            let mid_offset = cbor_size_of_list_header(self.inode_count) + mid * INODE_WIRE_SIZE;
+            let i = read_one_from_slice::<Inode>(
+                &self.mmapped_region[mid_offset..mid_offset + INODE_WIRE_SIZE],
+            )?;
+            if i.ino == ino {
+                return Ok(Some(i));
+            }
+
+            if i.ino < ino {
+                left = mid + 1;
+            } else {
+                // don't underflow...
+                if mid == 0 {
+                    break;
+                }
+                right = mid - 1;
+            };
+        }
+
+        Ok(None)
+    }
+}
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct DirEnt {
+    pub(crate) ino: Ino,
+    pub(crate) name: Vec<u8>,
+}
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct DirList {
+    // TODO: flags instead?
+    #[allow(dead_code)]
+    pub(crate) look_below: bool,
+    pub(crate) entries: Vec<DirEnt>,
+}
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct FileChunkList {
+    pub(crate) chunks: Vec<FileChunk>,
+}
+
+#[derive(Deserialize, Debug)]
+pub(crate) struct FileChunk {
+    pub(crate) blob: BlobRef,
+    pub(crate) len: u64,
+}
+
+const INODE_MODE_SIZE: usize = 1 /* mode */ + size_of::<u64>() * 2 /* major/minor/offset */;
+
+// InodeMode needs to have custom serialization because inodes must be a fixed size.
+#[derive(Debug, PartialEq, Eq)]
+pub(crate) enum InodeMode {
+    Unknown,
+    Fifo,
+    Chr { major: u64, minor: u64 },
+    Dir { offset: u64 },
+    Blk { major: u64, minor: u64 },
+    Reg { offset: u64 },
+    Lnk,
+    Sock,
+    Wht,
+}
+
+pub(crate) type Ino = u64;
+
+const INODE_SIZE: usize = size_of::<Ino>() + INODE_MODE_SIZE + 2 * size_of::<u32>() /* uid and gid */
++ size_of::<u16>() /* permissions */ + 1 /* Option<BlobRef> */ + BLOB_REF_SIZE;
+
+pub(crate) const INODE_WIRE_SIZE: usize = cbor_size_of_list_header(INODE_SIZE) + INODE_SIZE;
+
+#[derive(Debug, PartialEq, Eq)]
+pub(crate) struct Inode {
+    pub(crate) ino: Ino,
+    pub(crate) mode: InodeMode,
+    pub(crate) uid: u32,
+    pub(crate) gid: u32,
+    pub(crate) permissions: u16,
+    pub(crate) additional: Option<BlobRef>,
+}
+
+impl<'de> Deserialize<'de> for Inode {
+    fn deserialize<D>(deserializer: D) -> kernel::error::Result<Inode, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        struct InodeVisitor;
+
+        impl<'de> Visitor<'de> for InodeVisitor {
+            type Value = Inode;
+
+            fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
+                formatter.write_fmt(format_args!("expected {INODE_MODE_SIZE} bytes for Inode"))
+            }
+
+            fn visit_bytes<E>(self, v: &[u8]) -> kernel::error::Result<Inode, E>
+            where
+                E: SerdeError,
+            {
+                let state: [u8; INODE_SIZE] = v
+                    .try_into()
+                    .map_err(|_| SerdeError::invalid_length(v.len(), &self))?;
+
+                let mode = match state[8] {
+                    0 => InodeMode::Unknown,
+                    1 => InodeMode::Fifo,
+                    2 => {
+                        let major = u64::from_le_bytes(state[9..17].try_into().unwrap());
+                        let minor = u64::from_le_bytes(state[17..25].try_into().unwrap());
+                        InodeMode::Chr { major, minor }
+                    }
+                    4 => {
+                        let offset = u64::from_le_bytes(state[9..17].try_into().unwrap());
+                        InodeMode::Dir { offset }
+                    }
+                    6 => {
+                        let major = u64::from_le_bytes(state[9..17].try_into().unwrap());
+                        let minor = u64::from_le_bytes(state[17..25].try_into().unwrap());
+                        InodeMode::Blk { major, minor }
+                    }
+                    8 => {
+                        let offset = u64::from_le_bytes(state[9..17].try_into().unwrap());
+                        InodeMode::Reg { offset }
+                    }
+                    10 => InodeMode::Lnk,
+                    12 => InodeMode::Sock,
+                    14 => InodeMode::Wht,
+                    _ => {
+                        return Err(SerdeError::custom(format_args!(
+                            "bad inode mode value {}",
+                            state[8]
+                        )))
+                    }
+                };
+
+                let additional = if state[35] > 0 {
+                    Some(BlobRef::fixed_length_deserialize(
+                        state[36..36 + BLOB_REF_SIZE].try_into().unwrap(),
+                    )?)
+                } else {
+                    None
+                };
+
+                Ok(Inode {
+                    // ugh there must be a nicer way to do this with arrays, which we already have
+                    // from above...
+                    ino: u64::from_le_bytes(state[0..8].try_into().unwrap()),
+                    mode,
+                    uid: u32::from_le_bytes(state[25..29].try_into().unwrap()),
+                    gid: u32::from_le_bytes(state[29..33].try_into().unwrap()),
+                    permissions: u16::from_le_bytes(state[33..35].try_into().unwrap()),
+                    additional,
+                })
+            }
+        }
+
+        deserializer.deserialize_bytes(InodeVisitor)
+    }
+}
diff --git a/samples/rust/puzzle/types/cbor_helpers.rs b/samples/rust/puzzle/types/cbor_helpers.rs
new file mode 100644
index 000000000000..ae2aa4609428
--- /dev/null
+++ b/samples/rust/puzzle/types/cbor_helpers.rs
@@ -0,0 +1,9 @@
+pub(crate) const fn cbor_size_of_list_header(size: usize) -> usize {
+    match size {
+        0..=23 => 1,
+        24..=255 => 2,
+        256..=65535 => 3,
+        65536..=4294967295 => 4,
+        _ => 8,
+    }
+}
diff --git a/samples/rust/puzzlefs.rs b/samples/rust/puzzlefs.rs
index e7ce5078bc99..b149af4e66ce 100644
--- a/samples/rust/puzzlefs.rs
+++ b/samples/rust/puzzlefs.rs
@@ -6,6 +6,8 @@
 use kernel::prelude::*;
 use kernel::{c_str, file, fs, io_buffer::IoBufferWriter};
 
+mod puzzle;
+
 module_fs! {
     type: PuzzleFs,
     name: "puzzlefs",
-- 
2.40.1


  parent reply	other threads:[~2023-06-09  6:55 UTC|newest]

Thread overview: 134+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-09  6:29 [RFC PATCH 00/80] Rust PuzzleFS filesystem driver Ariel Miculas
2023-06-09  6:29 ` [PATCH 01/80] rust: add definitions for ref-counted inodes and dentries Ariel Miculas
2023-06-09  6:30 ` [PATCH 02/80] rust: add ability to register a file system Ariel Miculas
2023-06-09  9:23   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 03/80] rust: define fs context Ariel Miculas
2023-06-09  6:30 ` [PATCH 04/80] rust: add support for file system parameters Ariel Miculas
2023-06-09  6:30 ` [PATCH 05/80] rust: kernel: add libraries required by the filesystem abstractions Ariel Miculas
2023-06-09  9:46   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 06/80] rust: allow fs driver to initialise new superblocks Ariel Miculas
2023-06-09  6:30 ` [PATCH 07/80] rust: add `module_fs` macro Ariel Miculas
2023-06-09  6:30 ` [PATCH 08/80] WIP: rust: allow fs to be populated Ariel Miculas
2023-06-09  6:30 ` [PATCH 09/80] rust: kernel: backport the delay module from the rust branch Ariel Miculas
2023-06-09  9:29   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 10/80] rust: kernel: add container_of macro Ariel Miculas
2023-06-09  6:30 ` [PATCH 11/80] rust: kernel: add offset_of macro Ariel Miculas
2023-06-09  6:30 ` [PATCH 12/80] drop: Add crate::pr_warn declaration Ariel Miculas
2023-06-09  9:29   ` Miguel Ojeda
2023-06-09 10:46     ` Ariel Miculas (amiculas)
2023-06-09  6:30 ` [PATCH 13/80] rust: kernel: rename from_kernel_errno to from_errno Ariel Miculas
2023-06-09  9:56   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 14/80] rust: kernel: Rename from_pointer to from_foreing and into_pointer to into_foreign Ariel Miculas
2023-06-09  9:57   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 15/80] rust: kernel: add count_paren_items macro, needed by define_fs_params macro Ariel Miculas
2023-06-09  6:30 ` [PATCH 16/80] rust: helpers: add missing rust helper 'alloc_pages' Ariel Miculas
2023-06-09  9:57   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 17/80] kernel: configs: add qemu-busybox-min.config Ariel Miculas
2023-06-09  9:39   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 18/80] rust: kernel: format the rust code Ariel Miculas
2023-06-09  9:21   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 19/80] samples: puzzlefs: add initial puzzlefs sample, copied from rust_fs.rs Ariel Miculas
2023-06-09  6:30 ` [PATCH 20/80] kernel: configs: enable rust samples in rust.config Ariel Miculas
2023-06-09  9:25   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 22/80] rust: proc-macro2: add SPDX License Identifiers Ariel Miculas
2023-06-09  6:30 ` [PATCH 23/80] rust: proc-macro2: remove `unicode_ident` dependency Ariel Miculas
2023-06-09  6:30 ` [PATCH 24/80] rust: quote: import crate Ariel Miculas
2023-06-09  6:30 ` [PATCH 25/80] rust: quote: add SPDX License Identifiers Ariel Miculas
2023-06-09  6:30 ` [PATCH 27/80] rust: syn: " Ariel Miculas
2023-06-09  6:30 ` [PATCH 28/80] rust: syn: remove `unicode-ident` dependency Ariel Miculas
2023-06-09  6:30 ` [PATCH 30/80] rust: serde: add `no_fp_fmt_parse` support Ariel Miculas
2023-06-09  6:30 ` [PATCH 31/80] rust: serde: add SPDX License Identifiers Ariel Miculas
2023-06-10  0:19   ` Kent Overstreet
2023-06-10  6:43     ` Greg KH
2023-06-10 13:18       ` Kent Overstreet
2023-06-10 15:28         ` Greg KH
2023-06-10  0:25   ` Kent Overstreet
2023-06-10  9:04     ` Andreas Hindborg (Samsung)
2023-06-10 13:20       ` Kent Overstreet
2023-06-12  8:56         ` Ariel Miculas
2023-06-10  9:33     ` Miguel Ojeda
2023-06-12 11:58     ` Ariel Miculas
2023-06-15 15:05     ` Ariel Miculas
2023-06-17 16:04       ` Kent Overstreet
2023-06-09  6:30 ` [PATCH 33/80] rust: serde_derive: " Ariel Miculas
2023-06-09  6:30 ` [PATCH 34/80] rust: Kbuild: enable `proc-macro2`, `quote`, `syn`, `serde` and `serde_derive` Ariel Miculas
2023-06-09  6:30 ` [PATCH 35/80] rust: test `serde` support Ariel Miculas
2023-06-09  6:30 ` [PATCH 36/80] Add SAMPLE_RUST_SERDE in rust.config Ariel Miculas
2023-06-09  6:30 ` [PATCH 37/80] rust: kernel: fix compile errors after rebase to rust-next Ariel Miculas
2023-06-09  9:38   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 39/80] rust: serde_cbor: add SPDX License Identifiers Ariel Miculas
2023-06-09  6:30 ` [PATCH 40/80] rust: serde_cbor: add no_fp_fmt_parse support Ariel Miculas
2023-06-09  6:30 ` [PATCH 41/80] rust: Kbuild: enable serde_cbor Ariel Miculas
2023-06-09 10:21   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 42/80] samples: rust: add cbor serialize/deserialize example Ariel Miculas
2023-06-09  6:30 ` [PATCH 43/80] rust: serde_cbor: add support for serde_cbor's from_slice method by using a custom alloc_kernel feature Ariel Miculas
2023-06-09  9:55   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 44/80] rust: serde: add support for deserializing Vec with kernel_alloc feature Ariel Miculas
2023-06-09 10:10   ` Miguel Ojeda
2023-06-09  6:30 ` [PATCH 45/80] rust: file: Replace UnsafeCell with Opaque for File Ariel Miculas
2023-06-09  6:30 ` [PATCH 46/80] rust: kernel: implement fmt::Debug for CString Ariel Miculas
2023-06-09  6:30 ` [PATCH 47/80] samples: puzzlefs: rename RustFs to PuzzleFs Ariel Miculas
2023-06-09  6:30 ` Ariel Miculas [this message]
2023-06-09  6:30 ` [PATCH 49/80] rust: file: present the filesystem context to the open function Ariel Miculas
2023-06-09  6:30 ` [PATCH 50/80] rust: kernel: add an abstraction over vfsmount to allow cloning a new private mount Ariel Miculas
2023-06-09  6:30 ` [PATCH 51/80] rust: file: add from_path, from_path_in_root_mnt and read_with_offset methods to File Ariel Miculas
2023-06-09  6:30 ` [PATCH 52/80] samples: puzzlefs: pass the Vfsmount structure from open to read and return the contents of the data file inside /home/puzzlefs_oci Ariel Miculas
2023-06-09  6:30 ` [PATCH 53/80] rust: file: move from_path, from_path_in_root_mnt and read_with_offset methods to a RegularFile newtype Ariel Miculas
2023-06-09  6:30 ` [PATCH 54/80] rust: file: ensure RegularFile can only create regular files Ariel Miculas
2023-06-09  6:30 ` [PATCH 55/80] rust: file: add get_pos method to RegularFile Ariel Miculas
2023-06-09  6:30 ` [PATCH 56/80] rust: file: add methods read_to_end, get_file_size and update_pos " Ariel Miculas
2023-06-09  6:30 ` [PATCH 57/80] rust: file: define a minimal Read trait and implement it for RegularFile Ariel Miculas
2023-06-09  6:30 ` [PATCH 58/80] samples: puzzlefs: add cbor_get_array_size method Ariel Miculas
2023-06-09  6:30 ` [PATCH 59/80] samples: puzzlefs: add KernelError to WireFormatError and implement From conversion Ariel Miculas
2023-06-09  6:30 ` [PATCH 60/80] samples: puzzlefs: implement new for MetadataBlob Ariel Miculas
2023-06-09  6:30 ` [PATCH 61/80] samples: puzzlefs: build puzzlefs into the kernel, thus avoiding the need to export rust symbols Ariel Miculas
2023-06-09  6:31 ` [PATCH 62/80] rust: alloc: add try_clone for Vec<T> Ariel Miculas
2023-06-09  6:31 ` [PATCH 63/80] rust: alloc: add from_iter_fallible " Ariel Miculas
2023-06-09 10:06   ` Miguel Ojeda
2023-06-09  6:31 ` [PATCH 64/80] samples: puzzlefs: implement to_errno and from_errno for WireFormatError Ariel Miculas
2023-06-09  6:31 ` [PATCH 65/80] samples: puzzlefs: add TryReserveError (and from conversion) to WireFormatError Ariel Miculas
2023-06-09  6:31 ` [PATCH 66/80] samples: puzzlefs: add higher level inode related functionality Ariel Miculas
2023-06-09  6:31 ` [PATCH 67/80] samples: puzzlefs: populate the directory entries with the inodes from the puzzlefs metadata file Ariel Miculas
2023-06-09  6:31 ` [PATCH 68/80] rust: hex: import crate Ariel Miculas
2023-06-09  6:31 ` [PATCH 69/80] rust: hex: add SPDX license identifiers Ariel Miculas
2023-06-09  6:31 ` [PATCH 70/80] rust: Kbuild: enable `hex` Ariel Miculas
2023-06-09  6:31 ` [PATCH 71/80] rust: hex: implement FromHex trait and hex::decode using a custom kernel_alloc feature Ariel Miculas
2023-06-09  6:31 ` [PATCH 72/80] rust: hex: add encode_hex_iter and encode_hex_upper_iter methods Ariel Miculas
2023-06-09  6:31 ` [PATCH 73/80] rust: puzzlefs: add HexError to WireFormatError and implement the From conversion Ariel Miculas
2023-06-09  6:31 ` [PATCH 74/80] rust: puzzlefs: display the error value for WireFormatError::KernelError Ariel Miculas
2023-06-09  6:31 ` [PATCH 75/80] samples: puzzlefs: add Rootfs and Digest structs to types.rs Ariel Miculas
2023-06-09  6:31 ` [PATCH 76/80] samples: puzzlefs: implement the conversion from WireFormatError to kernel::error::Error Ariel Miculas
2023-06-09  6:31 ` [PATCH 77/80] rust: puzzlefs: read the puzzlefs image manifest instead of an individual metadata layer Ariel Miculas
2023-06-09  6:31 ` [PATCH 78/80] rust: puzzlefs: rename PuzzleFs to PuzzleFsModule to avoid confusion with the PuzzleFS struct Ariel Miculas
2023-06-09  6:31 ` [PATCH 79/80] rust: puzzlefs: add support for reading files Ariel Miculas
2023-06-09  6:31 ` [PATCH 80/80] rust: puzzlefs: add oci_root_dir and image_manifest filesystem parameters Ariel Miculas
2023-06-09 10:26 ` [RFC PATCH 00/80] Rust PuzzleFS filesystem driver Miguel Ojeda
2023-06-09 10:36 ` Christian Brauner
2023-06-09 11:42   ` Miguel Ojeda
     [not found]   ` <CH0PR11MB529981313ED5A1F815350E41CD51A@CH0PR11MB5299.namprd11.prod.outlook.com>
2023-06-09 11:45     ` Christian Brauner
2023-06-09 12:03       ` Ariel Miculas (amiculas)
2023-06-09 12:56         ` Gao Xiang
2023-06-09 12:07       ` Miguel Ojeda
2023-06-09 12:11         ` Ariel Miculas (amiculas)
2023-06-09 12:21           ` Greg KH
2023-06-09 13:05         ` Alice Ryhl
2023-06-09 12:20       ` Colin Walters
2023-06-09 12:42         ` Christian Brauner
2023-06-09 17:28           ` Serge Hallyn
2023-06-09 13:45         ` Ariel Miculas (amiculas)
2023-06-09 17:10           ` Trilok Soni
2023-06-09 17:16             ` Ariel Miculas (amiculas)
2023-06-09 17:41               ` Miguel Ojeda
2023-06-09 18:49                 ` James Bottomley
2023-06-09 19:08                   ` Miguel Ojeda
2023-06-09 19:11                   ` Ariel Miculas
2023-06-09 20:01                     ` James Bottomley
2023-06-10  9:34                     ` Miguel Ojeda
2023-06-09 18:43               ` James Bottomley
2023-06-09 18:59                 ` Ariel Miculas (amiculas)
2023-06-09 19:20                   ` Ariel Miculas
2023-06-09 19:45                     ` Trilok Soni
2023-06-09 19:53                   ` Alice Ryhl
2023-06-09 23:52   ` Kent Overstreet
2023-06-10  9:40     ` Miguel Ojeda
2023-06-10  0:09 ` Kent Overstreet

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230609063118.24852-49-amiculas@cisco.com \
    --to=amiculas@cisco.com \
    --cc=rust-for-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).