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}
@@ -220,6 +227,15 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
220227 inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
221228 bindings:: S_IFDIR
222229 }
230+ INodeType :: Reg => {
231+ // SAFETY: `generic_ro_fops` never changes, it's safe to reference it.
232+ inode. __bindgen_anon_3 . i_fop = unsafe { & bindings:: generic_ro_fops } ;
233+ inode. i_data . a_ops = & Tables :: < T > :: FILE_ADDRESS_SPACE_OPERATIONS ;
234+
235+ // SAFETY: The `i_mapping` pointer doesn't change and is valid.
236+ unsafe { bindings:: mapping_set_large_folios ( inode. i_mapping ) } ;
237+ bindings:: S_IFREG
238+ }
223239 } ;
224240
225241 inode. i_mode = ( params. mode & 0o777 ) | u16:: try_from ( mode) ?;
@@ -256,6 +272,9 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
256272pub enum INodeType {
257273 /// Directory type.
258274 Dir ,
275+
276+ /// Regular file type.
277+ Reg ,
259278}
260279
261280/// Required inode parameters.
@@ -604,6 +623,55 @@ impl<T: FileSystem + ?Sized> Tables<T> {
604623 } ,
605624 }
606625 }
626+
627+ const FILE_ADDRESS_SPACE_OPERATIONS : bindings:: address_space_operations =
628+ bindings:: address_space_operations {
629+ writepage : None ,
630+ read_folio : Some ( Self :: read_folio_callback) ,
631+ writepages : None ,
632+ dirty_folio : None ,
633+ readahead : None ,
634+ write_begin : None ,
635+ write_end : None ,
636+ bmap : None ,
637+ invalidate_folio : None ,
638+ release_folio : None ,
639+ free_folio : None ,
640+ direct_IO : None ,
641+ migrate_folio : None ,
642+ launder_folio : None ,
643+ is_partially_uptodate : None ,
644+ is_dirty_writeback : None ,
645+ error_remove_page : None ,
646+ swap_activate : None ,
647+ swap_deactivate : None ,
648+ swap_rw : None ,
649+ } ;
650+
651+ extern "C" fn read_folio_callback (
652+ _file : * mut bindings:: file ,
653+ folio : * mut bindings:: folio ,
654+ ) -> i32 {
655+ from_result ( || {
656+ // SAFETY: All pointers are valid and stable.
657+ let inode = unsafe {
658+ & * ( * ( * folio)
659+ . __bindgen_anon_1
660+ . page
661+ . __bindgen_anon_1
662+ . __bindgen_anon_1
663+ . mapping )
664+ . host
665+ . cast :: < INode < T > > ( )
666+ } ;
667+
668+ // SAFETY: The C contract guarantees that the folio is valid and locked, with ownership
669+ // of the lock transferred to the callee (this function). The folio is also guaranteed
670+ // not to outlive this function.
671+ T :: read_folio ( inode, unsafe { LockedFolio :: from_raw ( folio) } ) ?;
672+ Ok ( 0 )
673+ } )
674+ }
607675}
608676
609677/// Directory entry emitter.
@@ -678,7 +746,7 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
678746/// # mod module_ro_fs_sample {
679747/// use kernel::fs::{DirEmitter, INode, NewSuperBlock, SuperBlock};
680748/// use kernel::prelude::*;
681- /// use kernel::{c_str, fs, types::ARef};
749+ /// use kernel::{c_str, folio::LockedFolio, fs, types::ARef};
682750///
683751/// kernel::module_fs! {
684752/// type: MyFs,
@@ -700,6 +768,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
700768/// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
701769/// todo!()
702770/// }
771+ /// fn read_folio(_: &INode<Self>, _: LockedFolio<'_>) -> Result {
772+ /// todo!()
773+ /// }
703774/// }
704775/// # }
705776/// ```
0 commit comments