|
7 | 7 | //! C headers: [`include/linux/fs.h`](../../include/linux/fs.h)
|
8 | 8 |
|
9 | 9 | use crate::error::{code::*, from_result, to_result, Error, Result};
|
10 |
| -use crate::types::Opaque; |
| 10 | +use crate::types::{AlwaysRefCounted, Opaque}; |
11 | 11 | 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}; |
13 | 13 | use macros::{pin_data, pinned_drop};
|
14 | 14 |
|
15 | 15 | /// Maximum size of an inode.
|
@@ -94,6 +94,55 @@ impl PinnedDrop for Registration {
|
94 | 94 | }
|
95 | 95 | }
|
96 | 96 |
|
| 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 | + |
97 | 146 | /// A file system super block.
|
98 | 147 | ///
|
99 | 148 | /// Wraps the kernel's `struct super_block`.
|
|
0 commit comments