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
@@ -36,6 +39,9 @@ pub trait FileSystem {
3639
3740 /// Returns the inode corresponding to the directory entry with the given name.
3841 fn lookup ( parent : & INode < Self > , name : & [ u8 ] ) -> Result < ARef < INode < Self > > > ;
42+
43+ /// Reads the contents of the inode into the given folio.
44+ fn read_folio ( inode : & INode < Self > , folio : LockedFolio < ' _ > ) -> Result ;
3945}
4046
4147/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -74,6 +80,7 @@ impl From<INodeType> for DirEntryType {
7480 fn from ( value : INodeType ) -> Self {
7581 match value {
7682 INodeType :: Dir => DirEntryType :: Dir ,
83+ INodeType :: Reg => DirEntryType :: Reg ,
7784 }
7885 }
7986}
@@ -232,6 +239,15 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
232239 inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
233240 bindings:: S_IFDIR
234241 }
242+ INodeType :: Reg => {
243+ // SAFETY: `generic_ro_fops` never changes, it's safe to reference it.
244+ inode. __bindgen_anon_3 . i_fop = unsafe { & bindings:: generic_ro_fops } ;
245+ inode. i_data . a_ops = & Tables :: < T > :: FILE_ADDRESS_SPACE_OPERATIONS ;
246+
247+ // SAFETY: The `i_mapping` pointer doesn't change and is valid.
248+ unsafe { bindings:: mapping_set_large_folios ( inode. i_mapping ) } ;
249+ bindings:: S_IFREG
250+ }
235251 } ;
236252
237253 inode. i_mode = ( params. mode & 0o777 ) | u16:: try_from ( mode) ?;
@@ -268,6 +284,9 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
268284pub enum INodeType {
269285 /// Directory type.
270286 Dir ,
287+
288+ /// Regular file type.
289+ Reg ,
271290}
272291
273292/// Required inode parameters.
@@ -588,6 +607,55 @@ impl<T: FileSystem + ?Sized> Tables<T> {
588607 } ,
589608 }
590609 }
610+
611+ const FILE_ADDRESS_SPACE_OPERATIONS : bindings:: address_space_operations =
612+ bindings:: address_space_operations {
613+ writepage : None ,
614+ read_folio : Some ( Self :: read_folio_callback) ,
615+ writepages : None ,
616+ dirty_folio : None ,
617+ readahead : None ,
618+ write_begin : None ,
619+ write_end : None ,
620+ bmap : None ,
621+ invalidate_folio : None ,
622+ release_folio : None ,
623+ free_folio : None ,
624+ direct_IO : None ,
625+ migrate_folio : None ,
626+ launder_folio : None ,
627+ is_partially_uptodate : None ,
628+ is_dirty_writeback : None ,
629+ error_remove_page : None ,
630+ swap_activate : None ,
631+ swap_deactivate : None ,
632+ swap_rw : None ,
633+ } ;
634+
635+ extern "C" fn read_folio_callback (
636+ _file : * mut bindings:: file ,
637+ folio : * mut bindings:: folio ,
638+ ) -> i32 {
639+ from_result ( || {
640+ // SAFETY: All pointers are valid and stable.
641+ let inode = unsafe {
642+ & * ( * ( * folio)
643+ . __bindgen_anon_1
644+ . page
645+ . __bindgen_anon_1
646+ . __bindgen_anon_1
647+ . mapping )
648+ . host
649+ . cast :: < INode < T > > ( )
650+ } ;
651+
652+ // SAFETY: The C contract guarantees that the folio is valid and locked, with ownership
653+ // of the lock transferred to the callee (this function). The folio is also guaranteed
654+ // not to outlive this function.
655+ T :: read_folio ( inode, unsafe { LockedFolio :: from_raw ( folio) } ) ?;
656+ Ok ( 0 )
657+ } )
658+ }
591659}
592660
593661/// Directory entry emitter.
@@ -673,7 +741,7 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
673741/// # mod module_fs_sample {
674742/// use kernel::fs::{DirEmitter, INode, NewSuperBlock, SuperBlock, SuperParams};
675743/// use kernel::prelude::*;
676- /// use kernel::{c_str, fs, types::ARef};
744+ /// use kernel::{c_str, folio::LockedFolio, fs, types::ARef};
677745///
678746/// kernel::module_fs! {
679747/// type: MyFs,
@@ -698,6 +766,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
698766/// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
699767/// todo!()
700768/// }
769+ /// fn read_folio(_: &INode<Self>, _: LockedFolio<'_>) -> Result {
770+ /// todo!()
771+ /// }
701772/// }
702773/// # }
703774/// ```
0 commit comments