diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index e88a33270a..f2ac30d129 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -589,10 +589,24 @@ pub fn getns() -> Result { pub fn open>(path: T, flags: usize) -> Result { let _siglock = tmp_disable_signals(); - - let ns_fd = crate::current_namespace_fd()?; let fcntl_flags = flags & syscall::O_FCNTL_MASK; - openat_into_posix(ns_fd, path.as_ref(), flags, fcntl_flags) + // Two-step resolution (upstream contract, same as open_into_upper/unlink + // below): first obtain the scheme-root capability from the namespace + // manager (O_DIRECTORY open of the full path — the nsmgr only resolves the + // scheme part and dups its cap, it never opens into the provider), then + // open the reference AT that root so the kernel routes the request + // directly to the provider. The nsmgr is out of the data path entirely, + // which is what makes its single request loop unable to head-of-line + // block on a busy provider. + let redox_path = RedoxPath::from_absolute(path.as_ref()).ok_or(Error::new(EINVAL))?; + let (_, reference) = redox_path.as_parts().ok_or(Error::new(EINVAL))?; + let root_fd = FdGuard::new(openat_into_upper( + crate::current_namespace_fd()?, + path.as_ref(), + syscall::O_DIRECTORY | O_CLOEXEC, + 0, + )?); + openat_into_posix(root_fd.as_raw_fd(), reference.as_ref(), flags, fcntl_flags) } pub fn openat>( fd: usize,