88
99use crate :: error:: { code:: * , from_result, to_result, Error , Result } ;
1010use crate :: types:: { ARef , AlwaysRefCounted , Either , Opaque } ;
11- use crate :: { bindings, init:: PinInit , str:: CStr , time:: Timespec , try_pin_init, ThisModule } ;
11+ use crate :: {
12+ bindings, folio:: LockedFolio , init:: PinInit , str:: CStr , time:: Timespec , try_pin_init,
13+ ThisModule ,
14+ } ;
1215use core:: { marker:: PhantomData , marker:: PhantomPinned , mem:: ManuallyDrop , pin:: Pin , ptr} ;
1316use macros:: { pin_data, pinned_drop} ;
1417
@@ -41,6 +44,9 @@ pub trait FileSystem {
4144
4245 /// Returns the inode corresponding to the directory entry with the given name.
4346 fn lookup ( parent : & INode < Self > , name : & [ u8 ] ) -> Result < ARef < INode < Self > > > ;
47+
48+ /// Reads the contents of the inode into the given folio.
49+ fn read_folio ( inode : & INode < Self > , folio : LockedFolio < ' _ > ) -> Result ;
4450}
4551
4652/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -79,6 +85,7 @@ impl From<INodeType> for DirEntryType {
7985 fn from ( value : INodeType ) -> Self {
8086 match value {
8187 INodeType :: Dir => DirEntryType :: Dir ,
88+ INodeType :: Reg => DirEntryType :: Reg ,
8289 }
8390 }
8491}
@@ -231,6 +238,15 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
231238 inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
232239 bindings:: S_IFDIR
233240 }
241+ INodeType :: Reg => {
242+ // SAFETY: `generic_ro_fops` never changes, it's safe to reference it.
243+ inode. __bindgen_anon_3 . i_fop = unsafe { & bindings:: generic_ro_fops } ;
244+ inode. i_data . a_ops = & Tables :: < T > :: FILE_ADDRESS_SPACE_OPERATIONS ;
245+
246+ // SAFETY: The `i_mapping` pointer doesn't change and is valid.
247+ unsafe { bindings:: mapping_set_large_folios ( inode. i_mapping ) } ;
248+ bindings:: S_IFREG
249+ }
234250 } ;
235251
236252 inode. i_mode = ( params. mode & 0o777 ) | u16:: try_from ( mode) ?;
@@ -267,6 +283,9 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
267283pub enum INodeType {
268284 /// Directory type.
269285 Dir ,
286+
287+ /// Regular file type.
288+ Reg ,
270289}
271290
272291/// Required inode parameters.
@@ -612,6 +631,55 @@ impl<T: FileSystem + ?Sized> Tables<T> {
612631 } ,
613632 }
614633 }
634+
635+ const FILE_ADDRESS_SPACE_OPERATIONS : bindings:: address_space_operations =
636+ bindings:: address_space_operations {
637+ writepage : None ,
638+ read_folio : Some ( Self :: read_folio_callback) ,
639+ writepages : None ,
640+ dirty_folio : None ,
641+ readahead : None ,
642+ write_begin : None ,
643+ write_end : None ,
644+ bmap : None ,
645+ invalidate_folio : None ,
646+ release_folio : None ,
647+ free_folio : None ,
648+ direct_IO : None ,
649+ migrate_folio : None ,
650+ launder_folio : None ,
651+ is_partially_uptodate : None ,
652+ is_dirty_writeback : None ,
653+ error_remove_page : None ,
654+ swap_activate : None ,
655+ swap_deactivate : None ,
656+ swap_rw : None ,
657+ } ;
658+
659+ extern "C" fn read_folio_callback (
660+ _file : * mut bindings:: file ,
661+ folio : * mut bindings:: folio ,
662+ ) -> i32 {
663+ from_result ( || {
664+ // SAFETY: All pointers are valid and stable.
665+ let inode = unsafe {
666+ & * ( * ( * folio)
667+ . __bindgen_anon_1
668+ . page
669+ . __bindgen_anon_1
670+ . __bindgen_anon_1
671+ . mapping )
672+ . host
673+ . cast :: < INode < T > > ( )
674+ } ;
675+
676+ // SAFETY: The C contract guarantees that the folio is valid and locked, with ownership
677+ // of the lock transferred to the callee (this function). The folio is also guaranteed
678+ // not to outlive this function.
679+ T :: read_folio ( inode, unsafe { LockedFolio :: from_raw ( folio) } ) ?;
680+ Ok ( 0 )
681+ } )
682+ }
615683}
616684
617685/// Kernel module that exposes a single file system implemented by `T`.
@@ -642,7 +710,7 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
642710/// # mod module_ro_fs_sample {
643711/// use kernel::fs::{DirEntryType, INode, NewSuperBlock, SuperBlock};
644712/// use kernel::prelude::*;
645- /// use kernel::{c_str, fs, types::ARef};
713+ /// use kernel::{c_str, folio::LockedFolio, fs, types::ARef};
646714///
647715/// kernel::module_fs! {
648716/// type: MyFs,
@@ -668,6 +736,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
668736/// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
669737/// todo!()
670738/// }
739+ /// fn read_folio(_: &INode<Self>, _: LockedFolio<'_>) -> Result {
740+ /// todo!()
741+ /// }
671742/// }
672743/// # }
673744/// ```
0 commit comments