@@ -669,33 +669,40 @@ impl LockedProcFSInode {
669669 & self ,
670670 ns_name : & str ,
671671 ) -> Result < Arc < dyn IndexNode > , SystemError > {
672- // Convert namespace name to type
673- let ns_type = ThreadSelfNsFileType :: try_from ( ns_name) ?;
672+ // Convert namespace name to type,validate early.
673+ ThreadSelfNsFileType :: try_from ( ns_name) ?;
674674
675- // Check if file already exists without triggering recursive lookup
675+ let name = DName :: from ( ns_name) ;
676+
677+ // Fast-path: check if file already exists under the children map.
676678 {
677- let name = DName :: from ( ns_name) ;
678679 let guard = self . 0 . lock ( ) ;
679680 if let Some ( existing) = guard. children . get ( & name) {
680681 return Ok ( existing. clone ( ) ) ;
681682 }
682683 }
683684
684- // Create the namespace file. In Linux these appear as symlinks whose
685- // contents look like "ipc:[4026531839]". For now we model them as
686- // regular procfs files and implement the textual target via readlink,
687- // while `open()` returns a namespace fd.
688- let ns_file = self . create ( ns_name, FileType :: File , ModeType :: from_bits_truncate ( 0o444 ) ) ?;
689-
690- let ns_file_proc = ns_file
691- . as_any_ref ( )
692- . downcast_ref :: < LockedProcFSInode > ( )
693- . unwrap ( ) ;
694-
695- // Store namespace type in fd field (as u8 cast to i32)
696- ns_file_proc. 0 . lock ( ) . fdata . ftype = ProcFileType :: ProcThreadSelfNsChild ( ns_type) ;
697-
698- Ok ( ns_file)
685+ // Slow-path: try to create the namespace file. In Linux these appear as
686+ // symlinks whose contents look like "ipc:[4026531839]". For now we model
687+ // them as regular procfs files and implement the textual target via
688+ // readlink, while `open()` returns a namespace fd.
689+ match self . create ( ns_name, FileType :: File , ModeType :: from_bits_truncate ( 0o444 ) ) {
690+ Ok ( ns_file) => Ok ( ns_file) ,
691+ Err ( SystemError :: EEXIST ) => {
692+ // Lost a concurrent race: another thread created the same entry
693+ // between our initial check and create(). Look it up again and
694+ // return the existing node instead of failing.
695+ let guard = self . 0 . lock ( ) ;
696+ if let Some ( existing) = guard. children . get ( & name) {
697+ Ok ( existing. clone ( ) )
698+ } else {
699+ // Extremely unlikely: filesystem reported EEXIST but the
700+ // child is not present in the in-memory map. Treat as ENOENT.
701+ Err ( SystemError :: ENOENT )
702+ }
703+ }
704+ Err ( e) => Err ( e) ,
705+ }
699706 }
700707
701708 fn dynamical_find_fd ( & self , fd : & str ) -> Result < Arc < dyn IndexNode > , SystemError > {
@@ -963,9 +970,9 @@ impl IndexNode for LockedProcFSInode {
963970 if inode. metadata . file_type != FileType :: Dir {
964971 return Err ( SystemError :: ENOTDIR ) ;
965972 }
966- let name = DName :: from ( name) ;
973+ let dname = DName :: from ( name) ;
967974 // 如果有重名的,则返回
968- if inode. children . contains_key ( & name ) {
975+ if inode. children . contains_key ( & dname ) {
969976 return Err ( SystemError :: EEXIST ) ;
970977 }
971978
@@ -999,14 +1006,28 @@ impl IndexNode for LockedProcFSInode {
9991006 ftype : ProcFileType :: Default ,
10001007 fd : -1 ,
10011008 } ,
1002- dname : name . clone ( ) ,
1009+ dname : dname . clone ( ) ,
10031010 } ) ) ) ;
10041011
1005- // 初始化inode的自引用的weak指针
1006- result. 0 . lock ( ) . self_ref = Arc :: downgrade ( & result) ;
1012+ {
1013+ // 初始化子 inode 自引用 weak 指针,并在必要时为
1014+ // /proc/thread-self/ns/* 节点预先设置正确的 ftype,避免并发下
1015+ // 其他线程在 children.map 可见但 ftype 仍为 Default 的中间态。
1016+ let mut child_guard = result. 0 . lock ( ) ;
1017+ child_guard. self_ref = Arc :: downgrade ( & result) ;
1018+
1019+ // Special case: creating entries under /proc/thread-self/ns
1020+ if let ProcFileType :: ProcThreadSelfNsRoot = inode. fdata . ftype {
1021+ if let FileType :: File = file_type {
1022+ // 名称必须是合法的 namespace 名称,否则直接返回错误并“回滚”创建。
1023+ let ns_type = ThreadSelfNsFileType :: try_from ( name) ?;
1024+ child_guard. fdata . ftype = ProcFileType :: ProcThreadSelfNsChild ( ns_type) ;
1025+ }
1026+ }
1027+ }
10071028
10081029 // 将子inode插入父inode的B树中
1009- inode. children . insert ( name , result. clone ( ) ) ;
1030+ inode. children . insert ( dname , result. clone ( ) ) ;
10101031
10111032 return Ok ( result) ;
10121033 }
0 commit comments