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>,
Dave Chinner <david@fromorbit.com>
Cc: Kent Overstreet <kent.overstreet@gmail.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-fsdevel@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org,
Wedson Almeida Filho <walmeida@microsoft.com>
Subject: [RFC PATCH v2 09/30] rust: fs: generalise `File` for different file systems
Date: Tue, 14 May 2024 10:16:50 -0300 [thread overview]
Message-ID: <20240514131711.379322-10-wedsonaf@gmail.com> (raw)
In-Reply-To: <20240514131711.379322-1-wedsonaf@gmail.com>
From: Wedson Almeida Filho <walmeida@microsoft.com>
This is in preparation for allowing file operation implementations for
different file systems.
Also add an unspecified file system so that users of the `File` type
that don't care about the file system may continue to do so.
Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
---
rust/kernel/fs/file.rs | 53 ++++++++++++++++++++++++++++-------------
rust/kernel/fs/inode.rs | 1 -
2 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/rust/kernel/fs/file.rs b/rust/kernel/fs/file.rs
index 908e2672676f..b8386a396251 100644
--- a/rust/kernel/fs/file.rs
+++ b/rust/kernel/fs/file.rs
@@ -2,15 +2,18 @@
//! Files and file descriptors.
//!
-//! C headers: [`include/linux/fs.h`](../../../../include/linux/fs.h) and
-//! [`include/linux/file.h`](../../../../include/linux/file.h)
+//! This module allows Rust code to interact with and implement files.
+//!
+//! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) and
+//! [`include/linux/file.h`](srctree/include/linux/file.h)
+use super::{dentry::DEntry, inode::INode, FileSystem, UnspecifiedFS};
use crate::{
bindings,
error::{code::*, Error, Result},
types::{ARef, AlwaysRefCounted, Opaque},
};
-use core::ptr;
+use core::{marker::PhantomData, ptr};
/// Flags associated with a [`File`].
pub mod flags {
@@ -95,6 +98,8 @@ pub mod flags {
pub const O_RDWR: u32 = bindings::O_RDWR;
}
+/// A file.
+///
/// Wraps the kernel's `struct file`.
///
/// # Refcounting
@@ -139,7 +144,7 @@ pub mod flags {
/// * The Rust borrow-checker normally ensures this by enforcing that the `ARef<File>` from which
/// a `&File` is created outlives the `&File`.
///
-/// * Using the unsafe [`File::from_ptr`] means that it is up to the caller to ensure that the
+/// * Using the unsafe [`File::from_raw`] means that it is up to the caller to ensure that the
/// `&File` only exists while the reference count is positive.
///
/// * You can think of `fdget` as using an fd to look up an `ARef<File>` in the `struct
@@ -154,20 +159,20 @@ pub mod flags {
/// closed.
/// * A light refcount must be dropped before returning to userspace.
#[repr(transparent)]
-pub struct File(Opaque<bindings::file>);
+pub struct File<T: FileSystem + ?Sized = UnspecifiedFS>(Opaque<bindings::file>, PhantomData<T>);
// SAFETY: By design, the only way to access a `File` is via an immutable reference or an `ARef`.
// This means that the only situation in which a `File` can be accessed mutably is when the
// refcount drops to zero and the destructor runs. It is safe for that to happen on any thread, so
// it is ok for this type to be `Send`.
-unsafe impl Send for File {}
+unsafe impl<T: FileSystem + ?Sized> Send for File<T> {}
// SAFETY: All methods defined on `File` that take `&self` are safe to call even if other threads
// are concurrently accessing the same `struct file`, because those methods either access immutable
// properties or have proper synchronization to ensure that such accesses are safe.
-unsafe impl Sync for File {}
+unsafe impl<T: FileSystem + ?Sized> Sync for File<T> {}
-impl File {
+impl<T: FileSystem + ?Sized> File<T> {
/// Constructs a new `struct file` wrapper from a file descriptor.
///
/// The file descriptor belongs to the current process.
@@ -187,15 +192,17 @@ pub fn fget(fd: u32) -> Result<ARef<Self>, BadFdError> {
///
/// # Safety
///
- /// The caller must ensure that `ptr` points at a valid file and that the file's refcount is
- /// positive for the duration of 'a.
- pub unsafe fn from_ptr<'a>(ptr: *const bindings::file) -> &'a File {
+ /// Callers must ensure that:
+ ///
+ /// * `ptr` is valid and remains so for the duration of 'a.
+ /// * `ptr` has the correct file system type, or `T` is [`UnspecifiedFS`].
+ pub unsafe fn from_raw<'a>(ptr: *const bindings::file) -> &'a Self {
// SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
// duration of 'a. The cast is okay because `File` is `repr(transparent)`.
//
// INVARIANT: The safety requirements guarantee that the refcount does not hit zero during
// 'a.
- unsafe { &*ptr.cast() }
+ unsafe { &*ptr.cast::<Self>() }
}
/// Returns a raw pointer to the inner C struct.
@@ -215,20 +222,32 @@ pub fn flags(&self) -> u32 {
// TODO: Replace with `read_once` when available on the Rust side.
unsafe { core::ptr::addr_of!((*self.as_ptr()).f_flags).read_volatile() }
}
+
+ /// Returns the inode associated with the file.
+ pub fn inode(&self) -> &INode<T> {
+ // SAFETY: `f_inode` is an immutable field, so it's safe to read it.
+ unsafe { INode::from_raw((*self.0.get()).f_inode) }
+ }
+
+ /// Returns the dentry associated with the file.
+ pub fn dentry(&self) -> &DEntry<T> {
+ // SAFETY: `f_path` is an immutable field, so it's safe to read it. And will remain safe to
+ // read while the `&self` is valid.
+ unsafe { DEntry::from_raw((*self.0.get()).f_path.dentry) }
+ }
}
// SAFETY: The type invariants guarantee that `File` is always ref-counted. This implementation
// makes `ARef<File>` own a normal refcount.
-unsafe impl AlwaysRefCounted for File {
+unsafe impl<T: FileSystem + ?Sized> AlwaysRefCounted for File<T> {
fn inc_ref(&self) {
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
unsafe { bindings::get_file(self.as_ptr()) };
}
- unsafe fn dec_ref(obj: ptr::NonNull<File>) {
- // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we
- // may drop it. The cast is okay since `File` has the same representation as `struct file`.
- unsafe { bindings::fput(obj.cast().as_ptr()) }
+ unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
+ // SAFETY: The safety requirements guarantee that the refcount is nonzero.
+ unsafe { bindings::fput(obj.as_ref().0.get()) }
}
}
diff --git a/rust/kernel/fs/inode.rs b/rust/kernel/fs/inode.rs
index 4ccbb4145918..11df493314ea 100644
--- a/rust/kernel/fs/inode.rs
+++ b/rust/kernel/fs/inode.rs
@@ -39,7 +39,6 @@ impl<T: FileSystem + ?Sized> INode<T> {
///
/// * `ptr` is valid and remains so for the lifetime of the returned object.
/// * `ptr` has the correct file system type, or `T` is [`super::UnspecifiedFS`].
- #[allow(dead_code)]
pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::inode) -> &'a Self {
// SAFETY: The safety requirements guarantee that the cast below is ok.
unsafe { &*ptr.cast::<Self>() }
--
2.34.1
next prev parent reply other threads:[~2024-05-14 13:17 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-14 13:16 [RFC PATCH v2 00/30] Rust abstractions for VFS Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 01/30] rust: fs: add registration/unregistration of file systems Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 02/30] rust: fs: introduce the `module_fs` macro Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 03/30] samples: rust: add initial ro file system sample Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 04/30] rust: fs: introduce `FileSystem::fill_super` Wedson Almeida Filho
2024-05-20 19:38 ` Darrick J. Wong
2024-05-14 13:16 ` [RFC PATCH v2 05/30] rust: fs: introduce `INode<T>` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 06/30] rust: fs: introduce `DEntry<T>` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 07/30] rust: fs: introduce `FileSystem::init_root` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 08/30] rust: file: move `kernel::file` to `kernel::fs::file` Wedson Almeida Filho
2024-05-14 13:16 ` Wedson Almeida Filho [this message]
2024-05-14 13:16 ` [RFC PATCH v2 10/30] rust: fs: add empty file operations Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 11/30] rust: fs: introduce `file::Operations::read_dir` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 12/30] rust: fs: introduce `file::Operations::seek` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 13/30] rust: fs: introduce `file::Operations::read` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 14/30] rust: fs: add empty inode operations Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 15/30] rust: fs: introduce `inode::Operations::lookup` Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 16/30] rust: folio: introduce basic support for folios Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 17/30] rust: fs: add empty address space operations Wedson Almeida Filho
2024-05-14 13:16 ` [RFC PATCH v2 18/30] rust: fs: introduce `address_space::Operations::read_folio` Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 19/30] rust: fs: introduce `FileSystem::read_xattr` Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 20/30] rust: fs: introduce `FileSystem::statfs` Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 21/30] rust: fs: introduce more inode types Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 22/30] rust: fs: add per-superblock data Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 23/30] rust: fs: allow file systems backed by a block device Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 24/30] rust: fs: allow per-inode data Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 25/30] rust: fs: export file type from mode constants Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 26/30] rust: fs: allow populating i_lnk Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 27/30] rust: fs: add `iomap` module Wedson Almeida Filho
2024-05-20 19:32 ` Darrick J. Wong
2024-05-14 13:17 ` [RFC PATCH v2 28/30] rust: fs: add memalloc_nofs support Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 29/30] tarfs: introduce tar fs Wedson Almeida Filho
2024-05-14 13:17 ` [RFC PATCH v2 30/30] WIP: fs: ext2: add rust ro ext2 implementation Wedson Almeida Filho
2024-05-20 20:01 ` Darrick J. Wong
2024-05-31 14:34 ` [RFC PATCH v2 00/30] Rust abstractions for VFS Danilo Krummrich
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=20240514131711.379322-10-wedsonaf@gmail.com \
--to=wedsonaf@gmail.com \
--cc=brauner@kernel.org \
--cc=david@fromorbit.com \
--cc=gregkh@linuxfoundation.org \
--cc=kent.overstreet@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.