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
@@ -30,6 +33,9 @@ pub trait FileSystem {
3033
3134 /// Returns the inode corresponding to the directory entry with the given name.
3235 fn lookup ( parent : & INode < Self > , name : & [ u8 ] ) -> Result < ARef < INode < Self > > > ;
36+
37+ /// Reads the contents of the inode into the given folio.
38+ fn read_folio ( inode : & INode < Self > , folio : LockedFolio < ' _ > ) -> Result ;
3339}
3440
3541/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -68,6 +74,7 @@ impl From<INodeType> for DirEntryType {
6874 fn from ( value : INodeType ) -> Self {
6975 match value {
7076 INodeType :: Dir => DirEntryType :: Dir ,
77+ INodeType :: Reg => DirEntryType :: Reg ,
7178 }
7279 }
7380}
@@ -223,6 +230,15 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
223230 inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
224231 bindings:: S_IFDIR
225232 }
233+ INodeType :: Reg => {
234+ // SAFETY: `generic_ro_fops` never changes, it's safe to reference it.
235+ inode. __bindgen_anon_3 . i_fop = unsafe { & bindings:: generic_ro_fops } ;
236+ inode. i_data . a_ops = & Tables :: < T > :: FILE_ADDRESS_SPACE_OPERATIONS ;
237+
238+ // SAFETY: The `i_mapping` pointer doesn't change and is valid.
239+ unsafe { bindings:: mapping_set_large_folios ( inode. i_mapping ) } ;
240+ bindings:: S_IFREG
241+ }
226242 } ;
227243
228244 inode. i_mode = ( params. mode & 0o777 ) | u16:: try_from ( mode) ?;
@@ -259,6 +275,9 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
259275pub enum INodeType {
260276 /// Directory type.
261277 Dir ,
278+
279+ /// Regular file type.
280+ Reg ,
262281}
263282
264283/// Required inode parameters.
@@ -607,6 +626,55 @@ impl<T: FileSystem + ?Sized> Tables<T> {
607626 } ,
608627 }
609628 }
629+
630+ const FILE_ADDRESS_SPACE_OPERATIONS : bindings:: address_space_operations =
631+ bindings:: address_space_operations {
632+ writepage : None ,
633+ read_folio : Some ( Self :: read_folio_callback) ,
634+ writepages : None ,
635+ dirty_folio : None ,
636+ readahead : None ,
637+ write_begin : None ,
638+ write_end : None ,
639+ bmap : None ,
640+ invalidate_folio : None ,
641+ release_folio : None ,
642+ free_folio : None ,
643+ direct_IO : None ,
644+ migrate_folio : None ,
645+ launder_folio : None ,
646+ is_partially_uptodate : None ,
647+ is_dirty_writeback : None ,
648+ error_remove_page : None ,
649+ swap_activate : None ,
650+ swap_deactivate : None ,
651+ swap_rw : None ,
652+ } ;
653+
654+ extern "C" fn read_folio_callback (
655+ _file : * mut bindings:: file ,
656+ folio : * mut bindings:: folio ,
657+ ) -> i32 {
658+ from_result ( || {
659+ // SAFETY: All pointers are valid and stable.
660+ let inode = unsafe {
661+ & * ( * ( * folio)
662+ . __bindgen_anon_1
663+ . page
664+ . __bindgen_anon_1
665+ . __bindgen_anon_1
666+ . mapping )
667+ . host
668+ . cast :: < INode < T > > ( )
669+ } ;
670+
671+ // SAFETY: The C contract guarantees that the folio is valid and locked, with ownership
672+ // of the lock transferred to the callee (this function). The folio is also guaranteed
673+ // not to outlive this function.
674+ T :: read_folio ( inode, unsafe { LockedFolio :: from_raw ( folio) } ) ?;
675+ Ok ( 0 )
676+ } )
677+ }
610678}
611679
612680/// Directory entry emitter.
@@ -692,7 +760,7 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
692760/// # mod module_ro_fs_sample {
693761/// use kernel::fs::{DirEmitter, INode, NewSuperBlock, SuperBlock};
694762/// use kernel::prelude::*;
695- /// use kernel::{c_str, fs, types::ARef};
763+ /// use kernel::{c_str, folio::LockedFolio, fs, types::ARef};
696764///
697765/// kernel::module_fs! {
698766/// type: MyFs,
@@ -714,6 +782,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
714782/// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
715783/// todo!()
716784/// }
785+ /// fn read_folio(_: &INode<Self>, _: LockedFolio<'_>) -> Result {
786+ /// todo!()
787+ /// }
717788/// }
718789/// # }
719790/// ```
0 commit comments