77//! C headers: [`include/linux/fs.h`](../../include/linux/fs.h)
88
99use crate :: error:: { code:: * , from_result, to_result, Error , Result } ;
10- use crate :: types:: Opaque ;
10+ use crate :: types:: { AlwaysRefCounted , Opaque } ;
1111use 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 } ;
1313use macros:: { pin_data, pinned_drop} ;
1414
1515/// Maximum size of an inode.
@@ -94,13 +94,54 @@ impl PinnedDrop for Registration {
9494 }
9595}
9696
97- /// A superblock that is still being initialised.
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`.
98103///
99104/// # Invariants
100105///
101- /// The superblock is a newly-created one and this is the only active pointer to it.
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`.
102108#[ repr( transparent) ]
103- pub struct NewSuperBlock < T : FileSystem + ?Sized > ( bindings:: super_block , PhantomData < T > ) ;
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+ }
104145
105146/// A file system super block.
106147///
@@ -127,6 +168,14 @@ pub struct SuperParams {
127168 pub time_gran : u32 ,
128169}
129170
171+ /// A superblock that is still being initialised.
172+ ///
173+ /// # Invariants
174+ ///
175+ /// The superblock is a newly-created one and this is the only active pointer to it.
176+ #[ repr( transparent) ]
177+ pub struct NewSuperBlock < T : FileSystem + ?Sized > ( bindings:: super_block , PhantomData < T > ) ;
178+
130179struct Tables < T : FileSystem + ?Sized > ( T ) ;
131180impl < T : FileSystem + ?Sized > Tables < T > {
132181 const CONTEXT : bindings:: fs_context_operations = bindings:: fs_context_operations {
0 commit comments