rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Wedson Almeida Filho <wedsonaf@gmail.com>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>,
	Matthew Wilcox <willy@infradead.org>
Cc: Kent Overstreet <kent.overstreet@gmail.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-fsdevel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	Wedson Almeida Filho <walmeida@microsoft.com>
Subject: [RFC PATCH 09/19] rust: folio: introduce basic support for folios
Date: Wed, 18 Oct 2023 09:25:08 -0300	[thread overview]
Message-ID: <20231018122518.128049-10-wedsonaf@gmail.com> (raw)
In-Reply-To: <20231018122518.128049-1-wedsonaf@gmail.com>

From: Wedson Almeida Filho <walmeida@microsoft.com>

Allow Rust file systems to handle ref-counted folios.

Provide the minimum needed to implement `read_folio` (part of `struct
address_space_operations`) in read-only file systems and to read
uncached blocks.

Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
---
 rust/bindings/bindings_helper.h |   3 +
 rust/bindings/lib.rs            |   2 +
 rust/helpers.c                  |  81 ++++++++++++
 rust/kernel/folio.rs            | 215 ++++++++++++++++++++++++++++++++
 rust/kernel/lib.rs              |   1 +
 5 files changed, 302 insertions(+)
 create mode 100644 rust/kernel/folio.rs

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index ca1898ce9527..53a99ea512d1 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -11,6 +11,7 @@
 #include <linux/fs.h>
 #include <linux/fs_context.h>
 #include <linux/slab.h>
+#include <linux/pagemap.h>
 #include <linux/refcount.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
@@ -27,3 +28,5 @@ const slab_flags_t BINDINGS_SLAB_ACCOUNT = SLAB_ACCOUNT;
 const unsigned long BINDINGS_SB_RDONLY = SB_RDONLY;
 
 const loff_t BINDINGS_MAX_LFS_FILESIZE = MAX_LFS_FILESIZE;
+
+const size_t BINDINGS_PAGE_SIZE = PAGE_SIZE;
diff --git a/rust/bindings/lib.rs b/rust/bindings/lib.rs
index 426915d3fb57..a96b7f08e57d 100644
--- a/rust/bindings/lib.rs
+++ b/rust/bindings/lib.rs
@@ -59,3 +59,5 @@ mod bindings_helper {
 pub const SB_RDONLY: core::ffi::c_ulong = BINDINGS_SB_RDONLY;
 
 pub const MAX_LFS_FILESIZE: loff_t = BINDINGS_MAX_LFS_FILESIZE;
+
+pub const PAGE_SIZE: usize = BINDINGS_PAGE_SIZE;
diff --git a/rust/helpers.c b/rust/helpers.c
index c5a2bec6467d..f2ce3e7b688c 100644
--- a/rust/helpers.c
+++ b/rust/helpers.c
@@ -23,10 +23,14 @@
 #include <kunit/test-bug.h>
 #include <linux/bug.h>
 #include <linux/build_bug.h>
+#include <linux/cacheflush.h>
 #include <linux/err.h>
 #include <linux/errname.h>
 #include <linux/fs.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/pagemap.h>
 #include <linux/refcount.h>
 #include <linux/sched/signal.h>
 #include <linux/spinlock.h>
@@ -145,6 +149,77 @@ struct kunit *rust_helper_kunit_get_current_test(void)
 }
 EXPORT_SYMBOL_GPL(rust_helper_kunit_get_current_test);
 
+void *rust_helper_kmap(struct page *page)
+{
+	return kmap(page);
+}
+EXPORT_SYMBOL_GPL(rust_helper_kmap);
+
+void rust_helper_kunmap(struct page *page)
+{
+	kunmap(page);
+}
+EXPORT_SYMBOL_GPL(rust_helper_kunmap);
+
+void rust_helper_folio_get(struct folio *folio)
+{
+	folio_get(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_folio_get);
+
+void rust_helper_folio_put(struct folio *folio)
+{
+	folio_put(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_folio_put);
+
+struct page *rust_helper_folio_page(struct folio *folio, size_t n)
+{
+	return folio_page(folio, n);
+}
+
+loff_t rust_helper_folio_pos(struct folio *folio)
+{
+	return folio_pos(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_folio_pos);
+
+size_t rust_helper_folio_size(struct folio *folio)
+{
+	return folio_size(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_folio_size);
+
+void rust_helper_folio_mark_uptodate(struct folio *folio)
+{
+	folio_mark_uptodate(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_folio_mark_uptodate);
+
+void rust_helper_folio_set_error(struct folio *folio)
+{
+	folio_set_error(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_folio_set_error);
+
+void rust_helper_flush_dcache_folio(struct folio *folio)
+{
+	flush_dcache_folio(folio);
+}
+EXPORT_SYMBOL_GPL(rust_helper_flush_dcache_folio);
+
+void *rust_helper_kmap_local_folio(struct folio *folio, size_t offset)
+{
+	return kmap_local_folio(folio, offset);
+}
+EXPORT_SYMBOL_GPL(rust_helper_kmap_local_folio);
+
+void rust_helper_kunmap_local(const void *vaddr)
+{
+	kunmap_local(vaddr);
+}
+EXPORT_SYMBOL_GPL(rust_helper_kunmap_local);
+
 void rust_helper_i_uid_write(struct inode *inode, uid_t uid)
 {
 	i_uid_write(inode, uid);
@@ -163,6 +238,12 @@ off_t rust_helper_i_size_read(const struct inode *inode)
 }
 EXPORT_SYMBOL_GPL(rust_helper_i_size_read);
 
+void rust_helper_mapping_set_large_folios(struct address_space *mapping)
+{
+	mapping_set_large_folios(mapping);
+}
+EXPORT_SYMBOL_GPL(rust_helper_mapping_set_large_folios);
+
 /*
  * `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
  * use it in contexts where Rust expects a `usize` like slice (array) indices.
diff --git a/rust/kernel/folio.rs b/rust/kernel/folio.rs
new file mode 100644
index 000000000000..ef8a08b97962
--- /dev/null
+++ b/rust/kernel/folio.rs
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Groups of contiguous pages, folios.
+//!
+//! C headers: [`include/linux/mm.h`](../../include/linux/mm.h)
+
+use crate::error::{code::*, Result};
+use crate::types::{ARef, AlwaysRefCounted, Opaque, ScopeGuard};
+use core::{cmp::min, ptr};
+
+/// Wraps the kernel's `struct folio`.
+///
+/// # Invariants
+///
+/// Instances of this type are always ref-counted, that is, a call to `folio_get` ensures that the
+/// allocation remains valid at least until the matching call to `folio_put`.
+#[repr(transparent)]
+pub struct Folio(pub(crate) Opaque<bindings::folio>);
+
+// SAFETY: The type invariants guarantee that `Folio` is always ref-counted.
+unsafe impl AlwaysRefCounted for Folio {
+    fn inc_ref(&self) {
+        // SAFETY: The existence of a shared reference means that the refcount is nonzero.
+        unsafe { bindings::folio_get(self.0.get()) };
+    }
+
+    unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+        // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+        unsafe { bindings::folio_put(obj.cast().as_ptr()) }
+    }
+}
+
+impl Folio {
+    /// Tries to allocate a new folio.
+    ///
+    /// On success, returns a folio made up of 2^order pages.
+    pub fn try_new(order: u32) -> Result<UniqueFolio> {
+        if order > bindings::MAX_ORDER {
+            return Err(EDOM);
+        }
+
+        // SAFETY: We checked that `order` is within the max allowed value.
+        let f = ptr::NonNull::new(unsafe { bindings::folio_alloc(bindings::GFP_KERNEL, order) })
+            .ok_or(ENOMEM)?;
+
+        // SAFETY: The folio returned by `folio_alloc` is referenced. The ownership of the
+        // reference is transferred to the `ARef` instance.
+        Ok(UniqueFolio(unsafe { ARef::from_raw(f.cast()) }))
+    }
+
+    /// Returns the byte position of this folio in its file.
+    pub fn pos(&self) -> i64 {
+        // SAFETY: The folio is valid because the shared reference implies a non-zero refcount.
+        unsafe { bindings::folio_pos(self.0.get()) }
+    }
+
+    /// Returns the byte size of this folio.
+    pub fn size(&self) -> usize {
+        // SAFETY: The folio is valid because the shared reference implies a non-zero refcount.
+        unsafe { bindings::folio_size(self.0.get()) }
+    }
+
+    /// Flushes the data cache for the pages that make up the folio.
+    pub fn flush_dcache(&self) {
+        // SAFETY: The folio is valid because the shared reference implies a non-zero refcount.
+        unsafe { bindings::flush_dcache_folio(self.0.get()) }
+    }
+}
+
+/// A [`Folio`] that has a single reference to it.
+pub struct UniqueFolio(pub(crate) ARef<Folio>);
+
+impl UniqueFolio {
+    /// Maps the contents of a folio page into a slice.
+    pub fn map_page(&self, page_index: usize) -> Result<MapGuard<'_>> {
+        if page_index >= self.0.size() / bindings::PAGE_SIZE {
+            return Err(EDOM);
+        }
+
+        // SAFETY: We just checked that the index is within bounds of the folio.
+        let page = unsafe { bindings::folio_page(self.0 .0.get(), page_index) };
+
+        // SAFETY: `page` is valid because it was returned by `folio_page` above.
+        let ptr = unsafe { bindings::kmap(page) };
+
+        // SAFETY: We just mapped `ptr`, so it's valid for read.
+        let data = unsafe { core::slice::from_raw_parts(ptr.cast::<u8>(), bindings::PAGE_SIZE) };
+
+        Ok(MapGuard { data, page })
+    }
+}
+
+/// A mapped [`UniqueFolio`].
+pub struct MapGuard<'a> {
+    data: &'a [u8],
+    page: *mut bindings::page,
+}
+
+impl core::ops::Deref for MapGuard<'_> {
+    type Target = [u8];
+
+    fn deref(&self) -> &Self::Target {
+        self.data
+    }
+}
+
+impl Drop for MapGuard<'_> {
+    fn drop(&mut self) {
+        // SAFETY: A `MapGuard` instance is only created when `kmap` succeeds, so it's ok to unmap
+        // it when the guard is dropped.
+        unsafe { bindings::kunmap(self.page) };
+    }
+}
+
+/// A locked [`Folio`].
+pub struct LockedFolio<'a>(&'a Folio);
+
+impl LockedFolio<'_> {
+    /// Creates a new locked folio from a raw pointer.
+    ///
+    /// # Safety
+    ///
+    /// Callers must ensure that the folio is valid and locked. Additionally, that the
+    /// responsibility of unlocking is transferred to the new instance of [`LockedFolio`]. Lastly,
+    /// that the returned [`LockedFolio`] doesn't outlive the refcount that keeps it alive.
+    #[allow(dead_code)]
+    pub(crate) unsafe fn from_raw(folio: *const bindings::folio) -> Self {
+        let ptr = folio.cast();
+        // SAFETY: The safety requirements ensure that `folio` (from which `ptr` is derived) is
+        // valid and will remain valid while the `LockedFolio` instance lives.
+        Self(unsafe { &*ptr })
+    }
+
+    /// Marks the folio as being up to date.
+    pub fn mark_uptodate(&mut self) {
+        // SAFETY: The folio is valid because the shared reference implies a non-zero refcount.
+        unsafe { bindings::folio_mark_uptodate(self.0 .0.get()) }
+    }
+
+    /// Sets the error flag on the folio.
+    pub fn set_error(&mut self) {
+        // SAFETY: The folio is valid because the shared reference implies a non-zero refcount.
+        unsafe { bindings::folio_set_error(self.0 .0.get()) }
+    }
+
+    fn for_each_page(
+        &mut self,
+        offset: usize,
+        len: usize,
+        mut cb: impl FnMut(&mut [u8]) -> Result,
+    ) -> Result {
+        let mut remaining = len;
+        let mut next_offset = offset;
+
+        // Check that we don't overflow the folio.
+        let end = offset.checked_add(len).ok_or(EDOM)?;
+        if end > self.size() {
+            return Err(EINVAL);
+        }
+
+        while remaining > 0 {
+            let page_offset = next_offset & (bindings::PAGE_SIZE - 1);
+            let usable = min(remaining, bindings::PAGE_SIZE - page_offset);
+            // SAFETY: The folio is valid because the shared reference implies a non-zero refcount;
+            // `next_offset` is also guaranteed be lesss than the folio size.
+            let ptr = unsafe { bindings::kmap_local_folio(self.0 .0.get(), next_offset) };
+
+            // SAFETY: `ptr` was just returned by the `kmap_local_folio` above.
+            let _guard = ScopeGuard::new(|| unsafe { bindings::kunmap_local(ptr) });
+
+            // SAFETY: `kmap_local_folio` maps whole page so we know it's mapped for at least
+            // `usable` bytes.
+            let s = unsafe { core::slice::from_raw_parts_mut(ptr.cast::<u8>(), usable) };
+            cb(s)?;
+
+            next_offset += usable;
+            remaining -= usable;
+        }
+
+        Ok(())
+    }
+
+    /// Writes the given slice into the folio.
+    pub fn write(&mut self, offset: usize, data: &[u8]) -> Result {
+        let mut remaining = data;
+
+        self.for_each_page(offset, data.len(), |s| {
+            s.copy_from_slice(&remaining[..s.len()]);
+            remaining = &remaining[s.len()..];
+            Ok(())
+        })
+    }
+
+    /// Writes zeroes into the folio.
+    pub fn zero_out(&mut self, offset: usize, len: usize) -> Result {
+        self.for_each_page(offset, len, |s| {
+            s.fill(0);
+            Ok(())
+        })
+    }
+}
+
+impl core::ops::Deref for LockedFolio<'_> {
+    type Target = Folio;
+    fn deref(&self) -> &Self::Target {
+        self.0
+    }
+}
+
+impl Drop for LockedFolio<'_> {
+    fn drop(&mut self) {
+        // SAFETY: The folio is valid because the shared reference implies a non-zero refcount.
+        unsafe { bindings::folio_unlock(self.0 .0.get()) }
+    }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 00059b80c240..0e85b380da64 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -34,6 +34,7 @@
 mod allocator;
 mod build_assert;
 pub mod error;
+pub mod folio;
 pub mod fs;
 pub mod init;
 pub mod ioctl;
-- 
2.34.1


  parent reply	other threads:[~2023-10-18 12:26 UTC|newest]

Thread overview: 125+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-18 12:24 [RFC PATCH 00/19] Rust abstractions for VFS Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 01/19] rust: fs: add registration/unregistration of file systems Wedson Almeida Filho
2023-10-18 15:38   ` Benno Lossin
2024-01-10 18:32     ` Wedson Almeida Filho
2024-01-25  9:15       ` Benno Lossin
2023-10-18 12:25 ` [RFC PATCH 02/19] rust: fs: introduce the `module_fs` macro Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 03/19] samples: rust: add initial ro file system sample Wedson Almeida Filho
2023-10-28 16:18   ` Alice Ryhl
2024-01-10 18:25     ` Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 04/19] rust: fs: introduce `FileSystem::super_params` Wedson Almeida Filho
2023-10-18 16:34   ` Benno Lossin
2023-10-28 16:39     ` Alice Ryhl
2023-10-30  8:21       ` Benno Lossin
2023-10-30 21:36         ` Alice Ryhl
2023-10-20 15:04   ` Ariel Miculas (amiculas)
2024-01-03 12:25   ` Andreas Hindborg (Samsung)
2023-10-18 12:25 ` [RFC PATCH 05/19] rust: fs: introduce `INode<T>` Wedson Almeida Filho
2023-10-28 18:00   ` Alice Ryhl
2024-01-03 12:45     ` Andreas Hindborg (Samsung)
2024-01-03 12:54   ` Andreas Hindborg (Samsung)
2024-01-04  5:20     ` Darrick J. Wong
2024-01-04  9:57       ` Andreas Hindborg (Samsung)
2024-01-10  9:45     ` Benno Lossin
2024-01-04  5:14   ` Darrick J. Wong
2024-01-24 18:17     ` Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 06/19] rust: fs: introduce `FileSystem::init_root` Wedson Almeida Filho
2023-10-19 14:30   ` Benno Lossin
2023-10-20  0:52     ` Boqun Feng
2023-10-21 13:48       ` Benno Lossin
2023-10-21 15:57         ` Boqun Feng
2023-10-21 17:01           ` Matthew Wilcox
2023-10-21 19:33             ` Boqun Feng
2023-10-23  5:29               ` Dave Chinner
2023-10-23 12:55                 ` Wedson Almeida Filho
2023-10-30  2:29                   ` Dave Chinner
2023-10-31 20:49                     ` Wedson Almeida Filho
2023-11-08  4:54                       ` Dave Chinner
2023-11-08  6:15                         ` Wedson Almeida Filho
2023-10-20  0:30   ` Boqun Feng
2023-10-23 12:36     ` Wedson Almeida Filho
2024-01-03 13:29   ` Andreas Hindborg (Samsung)
2024-01-24  4:07     ` Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 07/19] rust: fs: introduce `FileSystem::read_dir` Wedson Almeida Filho
2023-10-21  8:33   ` Benno Lossin
2024-01-03 14:09   ` Andreas Hindborg (Samsung)
2024-01-21 21:00   ` Askar Safin
2024-01-21 21:51     ` Dave Chinner
2023-10-18 12:25 ` [RFC PATCH 08/19] rust: fs: introduce `FileSystem::lookup` Wedson Almeida Filho
2023-10-18 12:25 ` Wedson Almeida Filho [this message]
2023-10-18 17:17   ` [RFC PATCH 09/19] rust: folio: introduce basic support for folios Matthew Wilcox
2023-10-18 18:32     ` Wedson Almeida Filho
2023-10-18 19:21       ` Matthew Wilcox
2023-10-19 13:25         ` Wedson Almeida Filho
2023-10-20  4:11           ` Matthew Wilcox
2023-10-20 15:17             ` Matthew Wilcox
2023-10-23 12:32               ` Wedson Almeida Filho
2023-10-23 10:48             ` Andreas Hindborg (Samsung)
2023-10-23 14:28               ` Matthew Wilcox
2023-10-24 15:04                 ` Ariel Miculas (amiculas)
2023-10-23 12:29             ` Wedson Almeida Filho
2023-10-21  9:21   ` Benno Lossin
2023-10-18 12:25 ` [RFC PATCH 10/19] rust: fs: introduce `FileSystem::read_folio` Wedson Almeida Filho
2023-11-07 22:18   ` Matthew Wilcox
2023-11-07 22:22     ` Al Viro
2023-11-08  0:35       ` Wedson Almeida Filho
2023-11-08  0:56         ` Al Viro
2023-11-08  2:39           ` Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 11/19] rust: fs: introduce `FileSystem::read_xattr` Wedson Almeida Filho
2023-10-18 13:06   ` Ariel Miculas (amiculas)
2023-10-19 13:35     ` Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 12/19] rust: fs: introduce `FileSystem::statfs` Wedson Almeida Filho
2024-01-03 14:13   ` Andreas Hindborg (Samsung)
2024-01-04  5:33   ` Darrick J. Wong
2024-01-24  4:24     ` Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 13/19] rust: fs: introduce more inode types Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 14/19] rust: fs: add per-superblock data Wedson Almeida Filho
2023-10-25 15:51   ` Ariel Miculas (amiculas)
2023-10-26 13:46   ` Ariel Miculas (amiculas)
2024-01-03 14:16   ` Andreas Hindborg (Samsung)
2023-10-18 12:25 ` [RFC PATCH 15/19] rust: fs: add basic support for fs buffer heads Wedson Almeida Filho
2024-01-03 14:17   ` Andreas Hindborg (Samsung)
2023-10-18 12:25 ` [RFC PATCH 16/19] rust: fs: allow file systems backed by a block device Wedson Almeida Filho
2023-10-21 13:39   ` Benno Lossin
2024-01-24  4:14     ` Wedson Almeida Filho
2024-01-03 14:38   ` Andreas Hindborg (Samsung)
2023-10-18 12:25 ` [RFC PATCH 17/19] rust: fs: allow per-inode data Wedson Almeida Filho
2023-10-21 13:57   ` Benno Lossin
2024-01-03 14:39   ` Andreas Hindborg (Samsung)
2023-10-18 12:25 ` [RFC PATCH 18/19] rust: fs: export file type from mode constants Wedson Almeida Filho
2023-10-18 12:25 ` [RFC PATCH 19/19] tarfs: introduce tar fs Wedson Almeida Filho
2023-10-18 16:57   ` Matthew Wilcox
2023-10-18 17:05     ` Wedson Almeida Filho
2023-10-18 17:20       ` Matthew Wilcox
2023-10-18 18:07         ` Wedson Almeida Filho
2024-01-24  5:05   ` Matthew Wilcox
2024-01-24  5:23     ` Matthew Wilcox
2024-01-24 18:26       ` Wedson Almeida Filho
2024-01-24 21:05         ` Dave Chinner
2024-01-24 21:28           ` Matthew Wilcox
2024-01-24  5:34     ` Gao Xiang
2023-10-18 13:40 ` [RFC PATCH 00/19] Rust abstractions for VFS Ariel Miculas (amiculas)
2023-10-18 17:12   ` Wedson Almeida Filho
2023-10-29 20:31 ` Matthew Wilcox
2023-10-31 20:14   ` Wedson Almeida Filho
2024-01-03 18:02     ` Matthew Wilcox
2024-01-03 19:04       ` Wedson Almeida Filho
2024-01-03 19:53         ` Al Viro
2024-01-03 20:38           ` Kent Overstreet
2024-01-04  1:49         ` Matthew Wilcox
2024-01-09 18:25           ` Wedson Almeida Filho
2024-01-09 19:30             ` Matthew Wilcox
2024-01-03 19:14       ` Kent Overstreet
2024-01-03 20:41         ` Al Viro
2024-01-09 19:13           ` Wedson Almeida Filho
2024-01-09 19:25             ` Matthew Wilcox
2024-01-09 19:32               ` Greg Kroah-Hartman
2024-01-10  7:49                 ` Wedson Almeida Filho
2024-01-10  7:57                   ` Greg Kroah-Hartman
2024-01-10 12:56                   ` Matthew Wilcox
2024-01-09 22:19               ` Dave Chinner
2024-01-10 19:19                 ` Kent Overstreet
2024-01-24 13:08                   ` FUJITA Tomonori
2024-01-24 19:49                     ` Kent Overstreet
2024-01-05  0:04       ` David Howells
2024-01-05 15:54         ` Jarkko Sakkinen

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=20231018122518.128049-10-wedsonaf@gmail.com \
    --to=wedsonaf@gmail.com \
    --cc=brauner@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kent.overstreet@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    --cc=walmeida@microsoft.com \
    --cc=willy@infradead.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).