8
8
9
9
use crate :: error:: { code:: * , from_result, to_result, Error , Result } ;
10
10
use 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
+ } ;
12
15
use core:: { marker:: PhantomData , marker:: PhantomPinned , mem:: ManuallyDrop , pin:: Pin , ptr} ;
13
16
use macros:: { pin_data, pinned_drop} ;
14
17
@@ -36,6 +39,9 @@ pub trait FileSystem {
36
39
37
40
/// Returns the inode corresponding to the directory entry with the given name.
38
41
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 ;
39
45
}
40
46
41
47
/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -74,6 +80,7 @@ impl From<INodeType> for DirEntryType {
74
80
fn from ( value : INodeType ) -> Self {
75
81
match value {
76
82
INodeType :: Dir => DirEntryType :: Dir ,
83
+ INodeType :: Reg => DirEntryType :: Reg ,
77
84
}
78
85
}
79
86
}
@@ -232,6 +239,15 @@ impl<T: FileSystem + ?Sized> NewINode<T> {
232
239
inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
233
240
bindings:: S_IFDIR
234
241
}
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
+ }
235
251
} ;
236
252
237
253
inode. i_mode = ( params. mode & 0o777 ) | u16:: try_from ( mode) ?;
@@ -268,6 +284,9 @@ impl<T: FileSystem + ?Sized> Drop for NewINode<T> {
268
284
pub enum INodeType {
269
285
/// Directory type.
270
286
Dir ,
287
+
288
+ /// Regular file type.
289
+ Reg ,
271
290
}
272
291
273
292
/// Required inode parameters.
@@ -588,6 +607,55 @@ impl<T: FileSystem + ?Sized> Tables<T> {
588
607
} ,
589
608
}
590
609
}
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
+ }
591
659
}
592
660
593
661
/// Directory entry emitter.
@@ -673,7 +741,7 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
673
741
/// # mod module_fs_sample {
674
742
/// use kernel::fs::{DirEmitter, INode, NewSuperBlock, SuperBlock, SuperParams};
675
743
/// use kernel::prelude::*;
676
- /// use kernel::{c_str, fs, types::ARef};
744
+ /// use kernel::{c_str, folio::LockedFolio, fs, types::ARef};
677
745
///
678
746
/// kernel::module_fs! {
679
747
/// type: MyFs,
@@ -698,6 +766,9 @@ impl<T: FileSystem + ?Sized + Sync + Send> crate::InPlaceModule for Module<T> {
698
766
/// fn lookup(_: &INode<Self>, _: &[u8]) -> Result<ARef<INode<Self>>> {
699
767
/// todo!()
700
768
/// }
769
+ /// fn read_folio(_: &INode<Self>, _: LockedFolio<'_>) -> Result {
770
+ /// todo!()
771
+ /// }
701
772
/// }
702
773
/// # }
703
774
/// ```
0 commit comments