@@ -40,6 +40,9 @@ pub mod ro {
4040 pos : i64 ,
4141 report : impl FnMut ( & [ u8 ] , i64 , u64 , DirEntryType ) -> bool ,
4242 ) -> Result < i64 > ;
43+
44+ /// Returns the inode corresponding to the directory entry with the given name.
45+ fn lookup ( parent : & INode < Self > , name : & [ u8 ] ) -> Result < ARef < INode < Self > > > ;
4346 }
4447
4548 /// The types of directory entries reported by [`Type::read_dir`].
@@ -225,8 +228,7 @@ pub mod ro {
225228 let mode = match params. typ {
226229 INodeType :: Dir => {
227230 inode. __bindgen_anon_3 . i_fop = & Tables :: < T > :: DIR_FILE_OPERATIONS ;
228- // SAFETY: `simple_dir_inode_operations` never changes, it's safe to reference it.
229- inode. i_op = unsafe { & bindings:: simple_dir_inode_operations } ;
231+ inode. i_op = & Tables :: < T > :: DIR_INODE_OPERATIONS ;
230232 bindings:: S_IFDIR
231233 }
232234 } ;
@@ -559,6 +561,62 @@ pub mod ro {
559561 Ok ( 0 )
560562 } )
561563 }
564+
565+ const DIR_INODE_OPERATIONS : bindings:: inode_operations = bindings:: inode_operations {
566+ lookup : Some ( Self :: lookup_callback) ,
567+ get_link : None ,
568+ permission : None ,
569+ get_inode_acl : None ,
570+ readlink : None ,
571+ create : None ,
572+ link : None ,
573+ unlink : None ,
574+ symlink : None ,
575+ mkdir : None ,
576+ rmdir : None ,
577+ mknod : None ,
578+ rename : None ,
579+ setattr : None ,
580+ getattr : None ,
581+ listxattr : None ,
582+ fiemap : None ,
583+ update_time : None ,
584+ atomic_open : None ,
585+ tmpfile : None ,
586+ get_acl : None ,
587+ set_acl : None ,
588+ fileattr_set : None ,
589+ fileattr_get : None ,
590+ get_offset_ctx : None ,
591+ } ;
592+
593+ extern "C" fn lookup_callback (
594+ parent_ptr : * mut bindings:: inode ,
595+ dentry : * mut bindings:: dentry ,
596+ _flags : u32 ,
597+ ) -> * mut bindings:: dentry {
598+ // SAFETY: The C api guarantees that `parent_ptr` is a valid inode.
599+ let parent = unsafe { & * parent_ptr. cast :: < INode < T > > ( ) } ;
600+
601+ // SAFETY: The C api guarantees that `dentry` is valid for read. Since the name is
602+ // immutable, it's ok to read its length directly.
603+ let Ok ( name_len) = usize:: try_from ( unsafe { ( * dentry) . d_name . __bindgen_anon_1 . __bindgen_anon_1 . len }
604+ ) else {
605+ return ENOENT . to_ptr ( ) ;
606+ } ;
607+
608+ // SAFETY: The C api guarantees that `dentry` is valid for read. Since the name is
609+ // immutable, it's ok to read it directly.
610+ let name = unsafe { core:: slice:: from_raw_parts ( ( * dentry) . d_name . name , name_len) } ;
611+ match T :: lookup ( parent, name) {
612+ Err ( e) => e. to_ptr ( ) ,
613+ // SAFETY: The returned inode is valid and referenced (by the type invariants), so
614+ // it is ok to transfer this increment to `d_splice_alias`.
615+ Ok ( inode) => unsafe {
616+ bindings:: d_splice_alias ( ManuallyDrop :: new ( inode) . 0 . get ( ) , dentry)
617+ } ,
618+ }
619+ }
562620 }
563621
564622 /// Kernel module that exposes a single read-only file system implemented by `T`.
@@ -614,6 +672,12 @@ pub mod ro {
614672 /// # ) -> Result<i64> {
615673 /// # todo!()
616674 /// # }
675+ /// # fn lookup(
676+ /// # _: &fs::ro::INode<Self>,
677+ /// # _: &[u8],
678+ /// # ) -> Result<kernel::types::ARef<fs::ro::INode<Self>>> {
679+ /// # todo!()
680+ /// # }
617681 /// }
618682 /// ```
619683 #[ macro_export]
0 commit comments