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}
@@ -226,6 +233,15 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
226233 inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
227234 bindings:: S_IFDIR
228235 }
236+ INodeType :: Reg => {
237+ // SAFETY: `generic_ro_fops` never changes, it's safe to reference it.
238+ inode. __bindgen_anon_3 . i_fop = unsafe { & bindings:: generic_ro_fops } ;
239+ inode. i_data . a_ops = & Tables :: < T > :: FILE_ADDRESS_SPACE_OPERATIONS ;
240+
241+ // SAFETY: The `i_mapping` pointer doesn't change and is valid.
242+ unsafe { bindings:: mapping_set_large_folios ( inode. i_mapping ) } ;
243+ bindings:: S_IFREG
244+ }
229245 } ;
230246
231247 inode. i_mode = ( params. mode & 0o777 ) | u16:: try_from ( mode) ?;
@@ -262,6 +278,9 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
262278pub enum INodeType {
263279 /// Directory type.
264280 Dir ,
281+
282+ /// Regular file type.
283+ Reg ,
265284}
266285
267286/// Required inode parameters.
@@ -610,6 +629,55 @@ impl<T: FileSystem + ?Sized> Tables<T> {
610629 } ,
611630 }
612631 }
632+
633+ const FILE_ADDRESS_SPACE_OPERATIONS : bindings:: address_space_operations =
634+ bindings:: address_space_operations {
635+ writepage : None ,
636+ read_folio : Some ( Self :: read_folio_callback) ,
637+ writepages : None ,
638+ dirty_folio : None ,
639+ readahead : None ,
640+ write_begin : None ,
641+ write_end : None ,
642+ bmap : None ,
643+ invalidate_folio : None ,
644+ release_folio : None ,
645+ free_folio : None ,
646+ direct_IO : None ,
647+ migrate_folio : None ,
648+ launder_folio : None ,
649+ is_partially_uptodate : None ,
650+ is_dirty_writeback : None ,
651+ error_remove_page : None ,
652+ swap_activate : None ,
653+ swap_deactivate : None ,
654+ swap_rw : None ,
655+ } ;
656+
657+ extern "C" fn read_folio_callback (
658+ _file : * mut bindings:: file ,
659+ folio : * mut bindings:: folio ,
660+ ) -> i32 {
661+ from_result ( || {
662+ // SAFETY: All pointers are valid and stable.
663+ let inode = unsafe {
664+ & * ( * ( * folio)
665+ . __bindgen_anon_1
666+ . page
667+ . __bindgen_anon_1
668+ . __bindgen_anon_1
669+ . mapping )
670+ . host
671+ . cast :: < INode < T > > ( )
672+ } ;
673+
674+ // SAFETY: The C contract guarantees that the folio is valid and locked, with ownership
675+ // of the lock transferred to the callee (this function). The folio is also guaranteed
676+ // not to outlive this function.
677+ T :: read_folio ( inode, unsafe { LockedFolio :: from_raw ( folio) } ) ?;
678+ Ok ( 0 )
679+ } )
680+ }
613681}
614682
615683/// Directory entry emitter.
@@ -695,7 +763,7 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
695763/// # mod module_ro_fs_sample {
696764/// use kernel::fs::{DirEmitter, INode, NewSuperBlock, SuperBlock};
697765/// use kernel::prelude::*;
698- /// use kernel::{c_str, fs, types::ARef};
766+ /// use kernel::{c_str, folio::LockedFolio, fs, types::ARef};
699767///
700768/// kernel::module_fs! {
701769/// type: MyFs,
@@ -717,6 +785,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
717785/// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
718786/// todo!()
719787/// }
788+ /// fn read_folio(_: &INode<Self>, _: LockedFolio<'_>) -> Result {
789+ /// todo!()
790+ /// }
720791/// }
721792/// # }
722793/// ```
0 commit comments