Skip to content

Commit a448dc5

Browse files
committed
rust: fs: introduce INode<T>
Allow Rust file systems to handle typed and ref-counted inodes. This is in preparation for creating new inodes (for example, to create the root inode of a new superblock), which comes in the next patch in the series. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent 626056a commit a448dc5

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

rust/helpers.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/build_bug.h>
2626
#include <linux/err.h>
2727
#include <linux/errname.h>
28+
#include <linux/fs.h>
2829
#include <linux/mutex.h>
2930
#include <linux/refcount.h>
3031
#include <linux/sched/signal.h>
@@ -144,6 +145,12 @@ struct kunit *rust_helper_kunit_get_current_test(void)
144145
}
145146
EXPORT_SYMBOL_GPL(rust_helper_kunit_get_current_test);
146147

148+
off_t rust_helper_i_size_read(const struct inode *inode)
149+
{
150+
return i_size_read(inode);
151+
}
152+
EXPORT_SYMBOL_GPL(rust_helper_i_size_read);
153+
147154
/*
148155
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
149156
* use it in contexts where Rust expects a `usize` like slice (array) indices.

rust/kernel/fs.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
//! C headers: [`include/linux/fs.h`](../../include/linux/fs.h)
88
99
use crate::error::{code::*, from_result, to_result, Error, Result};
10-
use crate::types::Opaque;
10+
use crate::types::{AlwaysRefCounted, Opaque};
1111
use crate::{bindings, init::PinInit, str::CStr, try_pin_init, ThisModule};
12-
use core::{marker::PhantomData, marker::PhantomPinned, pin::Pin};
12+
use core::{marker::PhantomData, marker::PhantomPinned, pin::Pin, ptr};
1313
use macros::{pin_data, pinned_drop};
1414

1515
/// Maximum size of an inode.
@@ -94,6 +94,55 @@ impl PinnedDrop for Registration {
9494
}
9595
}
9696

97+
/// The number of an inode.
98+
pub type Ino = u64;
99+
100+
/// A node in the file system index (inode).
101+
///
102+
/// Wraps the kernel's `struct inode`.
103+
///
104+
/// # Invariants
105+
///
106+
/// Instances of this type are always ref-counted, that is, a call to `ihold` ensures that the
107+
/// allocation remains valid at least until the matching call to `iput`.
108+
#[repr(transparent)]
109+
pub struct INode<T: FileSystem + ?Sized>(Opaque<bindings::inode>, PhantomData<T>);
110+
111+
impl<T: FileSystem + ?Sized> INode<T> {
112+
/// Returns the number of the inode.
113+
pub fn ino(&self) -> Ino {
114+
// SAFETY: `i_ino` is immutable, and `self` is guaranteed to be valid by the existence of a
115+
// shared reference (&self) to it.
116+
unsafe { (*self.0.get()).i_ino }
117+
}
118+
119+
/// Returns the super-block that owns the inode.
120+
pub fn super_block(&self) -> &SuperBlock<T> {
121+
// SAFETY: `i_sb` is immutable, and `self` is guaranteed to be valid by the existence of a
122+
// shared reference (&self) to it.
123+
unsafe { &*(*self.0.get()).i_sb.cast() }
124+
}
125+
126+
/// Returns the size of the inode contents.
127+
pub fn size(&self) -> i64 {
128+
// SAFETY: `self` is guaranteed to be valid by the existence of a shared reference.
129+
unsafe { bindings::i_size_read(self.0.get()) }
130+
}
131+
}
132+
133+
// SAFETY: The type invariants guarantee that `INode` is always ref-counted.
134+
unsafe impl<T: FileSystem + ?Sized> AlwaysRefCounted for INode<T> {
135+
fn inc_ref(&self) {
136+
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
137+
unsafe { bindings::ihold(self.0.get()) };
138+
}
139+
140+
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
141+
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
142+
unsafe { bindings::iput(obj.cast().as_ptr()) }
143+
}
144+
}
145+
97146
/// A file system super block.
98147
///
99148
/// Wraps the kernel's `struct super_block`.

0 commit comments

Comments
 (0)