From: Ariel Miculas <amiculas@cisco.com>
To: rust-for-linux@vger.kernel.org
Cc: Wedson Almeida Filho <wedsonaf@google.com>
Subject: [PATCH 06/80] rust: allow fs driver to initialise new superblocks
Date: Fri, 9 Jun 2023 09:30:04 +0300 [thread overview]
Message-ID: <20230609063118.24852-7-amiculas@cisco.com> (raw)
In-Reply-To: <20230609063118.24852-1-amiculas@cisco.com>
From: Wedson Almeida Filho <wedsonaf@google.com>
They are also allowed to specify the type of superblock keying.
With this change, drivers get a new callback, `fill_super`, that they
need to implement to initialise new superblocks.
In subsequent commits, they'll be able to populate the root with
entries, but for now it's empty.
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
---
rust/kernel/fs.rs | 406 ++++++++++++++++++++++++++++++++--------
rust/kernel/fs/param.rs | 17 +-
samples/rust/rust_fs.rs | 14 +-
3 files changed, 357 insertions(+), 80 deletions(-)
diff --git a/rust/kernel/fs.rs b/rust/kernel/fs.rs
index e68b67b8adb0..fb4a814e1fc8 100644
--- a/rust/kernel/fs.rs
+++ b/rust/kernel/fs.rs
@@ -7,11 +7,31 @@
use crate::{bindings, error::code::*, str::CStr, ThisModule};
use crate::error::{to_result, from_kernel_result, Error, Result};
use crate::types::{AlwaysRefCounted, ForeignOwnable, ScopeGuard};
-use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin, ptr};
+use core::{cell::UnsafeCell, marker::PhantomData, marker::PhantomPinned, pin::Pin, ptr};
use macros::vtable;
pub mod param;
+/// Type of superblock keying.
+///
+/// It determines how C's `fs_context_operations::get_tree` is implemented.
+pub enum Super {
+ /// Only one such superblock may exist.
+ Single,
+
+ /// As [`Super::Single`], but reconfigure if it exists.
+ SingleReconf,
+
+ /// Superblocks with different data pointers may exist.
+ Keyed,
+
+ /// Multiple independent superblocks may exist.
+ Independent,
+
+ /// Uses a block device.
+ BlockDev,
+}
+
/// A file system context.
///
/// It is used to gather configuration to then mount or reconfigure a file system.
@@ -48,6 +68,16 @@ fn parse_monolithic<'a>(
) -> Result<Option<&'a mut [u8]>> {
Ok(None)
}
+
+ /// Returns the superblock data to be used by this file system context.
+ ///
+ /// This is only needed when [`Type::SUPER_TYPE`] is [`Super::Keyed`], otherwise it is never
+ /// called. In the former case, when the fs is being mounted, an existing superblock is reused
+ /// if one can be found with the same data as the returned value; otherwise a new superblock is
+ /// created.
+ fn tree_key(_data: &mut Self::Data) -> Result<T::Data> {
+ Err(ENOTSUPP)
+ }
}
struct Tables<T: Type + ?Sized>(T);
@@ -67,12 +97,22 @@ impl<T: Type + ?Sized> Tables<T> {
unsafe extern "C" fn free_callback(fc: *mut bindings::fs_context) {
// SAFETY: The callback contract guarantees that `fc` is valid.
- let ptr = unsafe { (*fc).fs_private };
+ let fc = unsafe { &*fc };
+
+ let ptr = fc.fs_private;
if !ptr.is_null() {
// SAFETY: `fs_private` was initialised with the result of a `to_pointer` call in
// `init_fs_context_callback`, so it's ok to call `from_foreign` here.
unsafe { <T::Context as Context<T>>::Data::from_foreign(ptr) };
}
+
+ let ptr = fc.s_fs_info;
+ if !ptr.is_null() {
+ // SAFETY: `s_fs_info` may be initialised with the result of a `to_pointer` call in
+ // `get_tree_callback` when keyed superblocks are used (`get_tree_keyed` sets it), so
+ // it's ok to call `from_foreign` here.
+ unsafe { T::Data::from_foreign(ptr) };
+ }
}
unsafe extern "C" fn parse_param_callback(
@@ -84,8 +124,8 @@ impl<T: Type + ?Sized> Tables<T> {
let ptr = unsafe { (*fc).fs_private };
// SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
- // `init_fs_context_callback` to the result of an `into_pointer` call. Since the
- // context is valid, `from_pointer` wasn't called yet, so `ptr` is valid. Additionally,
+ // `init_fs_context_callback` to the result of an `into_foreign` call. Since the
+ // context is valid, `from_foreign` wasn't called yet, so `ptr` is valid. Additionally,
// the callback contract guarantees that callbacks are serialised, so it is ok to
// mutably reference it.
let mut data =
@@ -126,73 +166,91 @@ impl<T: Type + ?Sized> Tables<T> {
unsafe extern "C" fn fill_super_callback(
sb_ptr: *mut bindings::super_block,
- _fc: *mut bindings::fs_context,
+ fc: *mut bindings::fs_context,
) -> core::ffi::c_int {
from_kernel_result! {
- // The following is temporary code to create the root inode and dentry. It will be
- // replaced with calls to Rust code.
-
- // SAFETY: The callback contract guarantees that `sb_ptr` is the only pointer to a
- // newly-allocated superblock, so it is safe to mutably reference it.
- let sb = unsafe { &mut *sb_ptr };
-
- sb.s_maxbytes = bindings::MAX_LFS_FILESIZE;
- sb.s_blocksize = crate::PAGE_SIZE as _;
- sb.s_blocksize_bits = bindings::PAGE_SHIFT as _;
- sb.s_magic = T::MAGIC as _;
- sb.s_op = &Tables::<T>::SUPER_BLOCK;
- sb.s_time_gran = 1;
-
- // Create and initialise the root inode.
-
- // SAFETY: `sb` was just created initialised, so it is safe pass it to `new_inode`.
- let inode = unsafe { bindings::new_inode(sb) };
- if inode.is_null() {
- return Err(ENOMEM);
- }
-
- {
- // SAFETY: This is a newly-created inode. No other references to it exist, so it is
- // safe to mutably dereference it.
- let inode = unsafe { &mut *inode };
-
- // SAFETY: `current_time` requires that `inode.sb` be valid, which is the case here
- // since we allocated the inode through the superblock.
- let time = unsafe { bindings::current_time(inode) };
- inode.i_ino = 1;
- inode.i_mode = (bindings::S_IFDIR | 0o755) as _;
- inode.i_mtime = time;
- inode.i_atime = time;
- inode.i_ctime = time;
-
- // SAFETY: `simple_dir_operations` never changes, it's safe to reference it.
- inode.__bindgen_anon_3.i_fop = unsafe { &bindings::simple_dir_operations };
-
- // SAFETY: `simple_dir_inode_operations` never changes, it's safe to reference it.
- inode.i_op = unsafe { &bindings::simple_dir_inode_operations };
-
- // SAFETY: `inode` is valid for write.
- unsafe { bindings::set_nlink(inode, 2) };
- }
-
- // SAFETY: `d_make_root` requires that `inode` be valid and referenced, which is the
- // case for this call.
- //
- // It takes over the inode, even on failure, so we don't need to clean it up.
- let dentry = unsafe { bindings::d_make_root(inode) };
- if dentry.is_null() {
- return Err(ENOMEM);
- }
+ // SAFETY: The callback contract guarantees that `fc` is valid. It also guarantees that
+ // the callbacks are serialised for a given `fc`, so it is safe to mutably dereference
+ // it.
+ let fc = unsafe { &mut *fc };
+ let ptr = core::mem::replace(&mut fc.fs_private, ptr::null_mut());
- sb.s_root = dentry;
+ // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
+ // `init_fs_context_callback` to the result of an `into_foreign` call. The context is
+ // being used to initialise a superblock, so we took over `ptr` (`fs_private` is set to
+ // null now) and call `from_foreign` below.
+ let data =
+ unsafe { <<T::Context as Context<T>>::Data as ForeignOwnable>::from_foreign(ptr) };
+
+ // SAFETY: The callback contract guarantees that `sb_ptr` is a unique pointer to a
+ // newly-created superblock.
+ let newsb = unsafe { NewSuperBlock::new(sb_ptr) };
+ T::fill_super(data, newsb)?;
Ok(0)
}
}
unsafe extern "C" fn get_tree_callback(fc: *mut bindings::fs_context) -> core::ffi::c_int {
- // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has the
- // right type and is a valid callback.
- unsafe { bindings::get_tree_nodev(fc, Some(Self::fill_super_callback)) }
+ // N.B. When new types are added below, we may need to update `kill_sb_callback` to ensure
+ // that we're cleaning up properly.
+ match T::SUPER_TYPE {
+ Super::Single => unsafe {
+ // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+ // the right type and is a valid callback.
+ bindings::get_tree_single(fc, Some(Self::fill_super_callback))
+ },
+ Super::SingleReconf => unsafe {
+ // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+ // the right type and is a valid callback.
+ bindings::get_tree_single_reconf(fc, Some(Self::fill_super_callback))
+ },
+ Super::Independent => unsafe {
+ // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+ // the right type and is a valid callback.
+ bindings::get_tree_nodev(fc, Some(Self::fill_super_callback))
+ },
+ Super::BlockDev => unsafe {
+ // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also has
+ // the right type and is a valid callback.
+ bindings::get_tree_bdev(fc, Some(Self::fill_super_callback))
+ },
+ Super::Keyed => {
+ from_kernel_result! {
+ // SAFETY: `fc` is valid per the callback contract.
+ let ctx = unsafe { &*fc };
+ let ptr = ctx.fs_private;
+
+ // SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
+ // `init_fs_context_callback` to the result of an `into_foreign` call. Since
+ // the context is valid, `from_foreign` wasn't called yet, so `ptr` is valid.
+ // Additionally, the callback contract guarantees that callbacks are
+ // serialised, so it is ok to mutably reference it.
+ let mut data = unsafe {
+ <<T::Context as Context<T>>::Data as ForeignOwnable>::borrow_mut(ptr)
+ };
+ let fs_data = T::Context::tree_key(&mut data)?;
+ let fs_data_ptr = fs_data.into_foreign();
+
+ // `get_tree_keyed` reassigns `ctx.s_fs_info`, which should be ok because
+ // nowhere else is it assigned a non-null value. However, we add the assert
+ // below to ensure that there are no unexpected paths on the C side that may do
+ // this.
+ assert_eq!(ctx.s_fs_info, core::ptr::null_mut());
+
+ // SAFETY: `fc` is valid per the callback contract. `fill_super_callback` also
+ // has the right type and is a valid callback. Lastly, we just called
+ // `into_foreign` above, so `fs_data_ptr` is also valid.
+ to_result(unsafe {
+ bindings::get_tree_keyed(
+ fc,
+ Some(Self::fill_super_callback),
+ fs_data_ptr as _,
+ )
+ })?;
+ Ok(0)
+ }
+ }
+ }
}
unsafe extern "C" fn reconfigure_callback(_fc: *mut bindings::fs_context) -> core::ffi::c_int {
@@ -208,8 +266,8 @@ impl<T: Type + ?Sized> Tables<T> {
let ptr = unsafe { (*fc).fs_private };
// SAFETY: The value of `ptr` (coming from `fs_private` was initialised in
- // `init_fs_context_callback` to the result of an `into_pointer` call. Since the
- // context is valid, `from_pointer` wasn't called yet, so `ptr` is valid. Additionally,
+ // `init_fs_context_callback` to the result of an `into_foreign` call. Since the
+ // context is valid, `from_foreign` wasn't called yet, so `ptr` is valid. Additionally,
// the callback contract guarantees that callbacks are serialised, so it is ok to
// mutably reference it.
let mut data =
@@ -270,18 +328,25 @@ pub trait Type {
/// The context used to build fs configuration before it is mounted or reconfigured.
type Context: Context<Self> + ?Sized;
+ /// Data associated with each file system instance.
+ type Data: ForeignOwnable + Send + Sync = ();
+
+ /// Determines how superblocks for this file system type are keyed.
+ const SUPER_TYPE: Super;
+
/// The name of the file system type.
const NAME: &'static CStr;
- /// The magic number associated with the file system.
- ///
- /// This is normally one of the values in `include/uapi/linux/magic.h`.
- const MAGIC: u32;
-
/// The flags of this file system type.
///
/// It is a combination of the flags in the [`flags`] module.
const FLAGS: i32;
+
+ /// Initialises a super block for this file system type.
+ fn fill_super(
+ data: <Self::Context as Context<Self>>::Data,
+ sb: NewSuperBlock<'_, Self>,
+ ) -> Result<&SuperBlock<Self>>;
}
/// File system flags.
@@ -425,14 +490,33 @@ unsafe fn unregister_keys(fs: *mut bindings::file_system_type) {
}
unsafe extern "C" fn kill_sb_callback<T: Type + ?Sized>(sb_ptr: *mut bindings::super_block) {
- // SAFETY: We always call `get_tree_nodev` from `get_tree_callback`, so we never have a
- // device, so it is ok to call the function below. Additionally, the callback contract
- // guarantees that `sb_ptr` is valid.
- unsafe { bindings::kill_anon_super(sb_ptr) }
-
- // SAFETY: The callback contract guarantees that `sb_ptr` is valid, and the `kill_sb`
- // callback being called implies that the `s_type` is also valid.
- unsafe { Self::unregister_keys((*sb_ptr).s_type) };
+ if let Super::BlockDev = T::SUPER_TYPE {
+ // SAFETY: When the superblock type is `BlockDev`, we have a block device so it's safe
+ // to call `kill_block_super`. Additionally, the callback contract guarantees that
+ // `sb_ptr` is valid.
+ unsafe { bindings::kill_block_super(sb_ptr) }
+ } else {
+ // SAFETY: We always call a `get_tree_nodev` variant from `get_tree_callback` without a
+ // device when `T::SUPER_TYPE` is not `BlockDev`, so we never have a device in such
+ // cases, therefore it is ok to call the function below. Additionally, the callback
+ // contract guarantees that `sb_ptr` is valid.
+ unsafe { bindings::kill_anon_super(sb_ptr) }
+ }
+
+ // SAFETY: The callback contract guarantees that `sb_ptr` is valid.
+ let sb = unsafe { &*sb_ptr };
+
+ // SAFETY: The `kill_sb` callback being called implies that the `s_type` field is valid.
+ unsafe { Self::unregister_keys(sb.s_type) };
+
+ let ptr = sb.s_fs_info;
+ if !ptr.is_null() {
+ // SAFETY: The only place where `s_fs_info` is assigned is `NewSuperBlock::init`, where
+ // it's initialised with the result of a `to_pointer` call. We checked above that ptr
+ // is non-null because it would be null if we never reached the point where we init the
+ // field.
+ unsafe { T::Data::from_foreign(ptr) };
+ }
}
}
@@ -446,6 +530,172 @@ fn drop(&mut self) {
}
}
+/// State of [`NewSuperBlock`] that indicates that [`NewSuperBlock::init`] needs to be called
+/// eventually.
+pub struct NeedsInit;
+
+/// State of [`NewSuperBlock`] that indicates that [`NewSuperBlock::init_root`] needs to be called
+/// eventually.
+pub struct NeedsRoot;
+
+/// Required superblock parameters.
+///
+/// This is used in [`NewSuperBlock::init`].
+pub struct SuperParams {
+ /// The magic number of the superblock.
+ pub magic: u32,
+
+ /// The size of a block in powers of 2 (i.e., for a value of `n`, the size is `2^n`.
+ pub blocksize_bits: u8,
+
+ /// Maximum size of a file.
+ pub maxbytes: i64,
+
+ /// Granularity of c/m/atime in ns (cannot be worse than a second).
+ pub time_gran: u32,
+}
+
+impl SuperParams {
+ /// Default value for instances of [`SuperParams`].
+ pub const DEFAULT: Self = Self {
+ magic: 0,
+ blocksize_bits: crate::PAGE_SIZE as _,
+ maxbytes: bindings::MAX_LFS_FILESIZE,
+ time_gran: 1,
+ };
+}
+
+/// A superblock that is still being initialised.
+///
+/// It uses type states to ensure that callers use the right sequence of calls.
+///
+/// # Invariants
+///
+/// The superblock is a newly-created one and this is the only active pointer to it.
+pub struct NewSuperBlock<'a, T: Type + ?Sized, S = NeedsInit> {
+ sb: *mut bindings::super_block,
+ _p: PhantomData<(&'a T, S)>,
+}
+
+impl<'a, T: Type + ?Sized> NewSuperBlock<'a, T, NeedsInit> {
+ /// Creates a new instance of [`NewSuperBlock`].
+ ///
+ /// # Safety
+ ///
+ /// `sb` must point to a newly-created superblock and it must be the only active pointer to it.
+ unsafe fn new(sb: *mut bindings::super_block) -> Self {
+ // INVARIANT: The invariants are satisfied by the safety requirements of this function.
+ Self {
+ sb,
+ _p: PhantomData,
+ }
+ }
+
+ /// Initialises the superblock so that it transitions to the [`NeedsRoot`] type state.
+ pub fn init(
+ self,
+ data: T::Data,
+ params: &SuperParams,
+ ) -> Result<NewSuperBlock<'a, T, NeedsRoot>> {
+ // SAFETY: The type invariant guarantees that `self.sb` is the only pointer to a
+ // newly-allocated superblock, so it is safe to mutably reference it.
+ let sb = unsafe { &mut *self.sb };
+
+ sb.s_magic = params.magic as _;
+ sb.s_op = &Tables::<T>::SUPER_BLOCK;
+ sb.s_maxbytes = params.maxbytes;
+ sb.s_time_gran = params.time_gran;
+ sb.s_blocksize_bits = params.blocksize_bits;
+ sb.s_blocksize = 1;
+ if sb.s_blocksize.leading_zeros() < params.blocksize_bits.into() {
+ return Err(EINVAL);
+ }
+ sb.s_blocksize = 1 << sb.s_blocksize_bits;
+
+ // Keyed file systems already have `s_fs_info` initialised.
+ let info = data.into_foreign() as *mut _;
+ if let Super::Keyed = T::SUPER_TYPE {
+ // SAFETY: We just called `into_foreign` above.
+ unsafe { T::Data::from_foreign(info) };
+
+ if sb.s_fs_info != info {
+ return Err(EINVAL);
+ }
+ } else {
+ sb.s_fs_info = info;
+ }
+
+ Ok(NewSuperBlock {
+ sb: self.sb,
+ _p: PhantomData,
+ })
+ }
+}
+
+impl<'a, T: Type + ?Sized> NewSuperBlock<'a, T, NeedsRoot> {
+ /// Initialises the root of the superblock.
+ pub fn init_root(self) -> Result<&'a SuperBlock<T>> {
+ // The following is temporary code to create the root inode and dentry. It will be replaced
+ // once we allow inodes and dentries to be created directly from Rust code.
+
+ // SAFETY: `sb` is initialised (`NeedsRoot` typestate implies it), so it is safe to pass it
+ // to `new_inode`.
+ let inode = unsafe { bindings::new_inode(self.sb) };
+ if inode.is_null() {
+ return Err(ENOMEM);
+ }
+
+ {
+ // SAFETY: This is a newly-created inode. No other references to it exist, so it is
+ // safe to mutably dereference it.
+ let inode = unsafe { &mut *inode };
+
+ // SAFETY: `current_time` requires that `inode.sb` be valid, which is the case here
+ // since we allocated the inode through the superblock.
+ let time = unsafe { bindings::current_time(inode) };
+ inode.i_ino = 1;
+ inode.i_mode = (bindings::S_IFDIR | 0o755) as _;
+ inode.i_mtime = time;
+ inode.i_atime = time;
+ inode.i_ctime = time;
+
+ // SAFETY: `simple_dir_operations` never changes, it's safe to reference it.
+ inode.__bindgen_anon_3.i_fop = unsafe { &bindings::simple_dir_operations };
+
+ // SAFETY: `simple_dir_inode_operations` never changes, it's safe to reference it.
+ inode.i_op = unsafe { &bindings::simple_dir_inode_operations };
+
+ // SAFETY: `inode` is valid for write.
+ unsafe { bindings::set_nlink(inode, 2) };
+ }
+
+ // SAFETY: `d_make_root` requires that `inode` be valid and referenced, which is the
+ // case for this call.
+ //
+ // It takes over the inode, even on failure, so we don't need to clean it up.
+ let dentry = unsafe { bindings::d_make_root(inode) };
+ if dentry.is_null() {
+ return Err(ENOMEM);
+ }
+
+ // SAFETY: The typestate guarantees that `self.sb` is valid.
+ unsafe { (*self.sb).s_root = dentry };
+
+ // SAFETY: The typestate guarantees that `self.sb` is initialised and we just finished
+ // setting its root, so it's a fully ready superblock.
+ Ok(unsafe { &mut *self.sb.cast() })
+ }
+}
+
+/// A file system super block.
+///
+/// Wraps the kernel's `struct super_block`.
+#[repr(transparent)]
+pub struct SuperBlock<T: Type + ?Sized>(
+ pub(crate) UnsafeCell<bindings::super_block>,
+ PhantomData<T>,
+);
+
/// Wraps the kernel's `struct inode`.
///
/// # Invariants
diff --git a/rust/kernel/fs/param.rs b/rust/kernel/fs/param.rs
index f0b4393b6b67..44b4e895a1eb 100644
--- a/rust/kernel/fs/param.rs
+++ b/rust/kernel/fs/param.rs
@@ -487,9 +487,24 @@ macro_rules! count_brace_items {
///
/// # impl fs::Type for Example {
/// # type Context = Self;
+/// # const SUPER_TYPE: fs::Super = fs::Super::Independent;
/// # const NAME: &'static CStr = c_str!("example");
/// # const FLAGS: i32 = 0;
-/// # const MAGIC: u32 = 0x6578616d;
+/// #
+/// # fn fill_super<'a>(
+/// # _data: Box<State>,
+/// # sb: fs::NewSuperBlock<'_, Self>,
+/// # ) -> Result<&fs::SuperBlock<Self>> {
+/// # let sb = sb.init(
+/// # (),
+/// # &fs::SuperParams {
+/// # magic: 0x6578616d,
+/// # ..fs::SuperParams::DEFAULT
+/// # },
+/// # )?;
+/// # let sb = sb.init_root()?;
+/// # Ok(sb)
+/// # }
/// # }
/// ```
#[macro_export]
diff --git a/samples/rust/rust_fs.rs b/samples/rust/rust_fs.rs
index acaa603b0bb2..5d8880d5830b 100644
--- a/samples/rust/rust_fs.rs
+++ b/samples/rust/rust_fs.rs
@@ -41,9 +41,21 @@ fn try_new() -> Result {
impl fs::Type for RustFs {
type Context = Self;
+ const SUPER_TYPE: fs::Super = fs::Super::Independent;
const NAME: &'static CStr = c_str!("rustfs");
const FLAGS: i32 = fs::flags::USERNS_MOUNT;
- const MAGIC: u32 = 0x72757374;
+
+ fn fill_super(_data: (), sb: fs::NewSuperBlock<'_, Self>) -> Result<&fs::SuperBlock<Self>> {
+ let sb = sb.init(
+ (),
+ &fs::SuperParams {
+ magic: 0x72757374,
+ ..fs::SuperParams::DEFAULT
+ },
+ )?;
+ let sb = sb.init_root()?;
+ Ok(sb)
+ }
}
struct FsModule {
--
2.40.1
next prev 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 ` Ariel Miculas [this message]
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 ` [PATCH 48/80] samples: puzzlefs: add basic deserializing support for the puzzlefs metadata Ariel Miculas
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-7-amiculas@cisco.com \
--to=amiculas@cisco.com \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@google.com \
/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).