redox-rt: two-step namespace resolution in sys::open (upstream contract)

sys::open still sent the FULL path in a single SYS_OPENAT_INTO on the
namespace fd — the pre-fd-allocation contract that forced the namespace
manager to proxy every open with a blocking openat into the provider
(the mini boot-freeze head-of-line; see base initnsmgr commit adopting
the upstream capability-handoff path).

Port the upstream two-step (verbatim from upstream/master, matching the
open_into_upper and unlink helpers below that were already synced):
1. openat(ns_fd, full_path, O_DIRECTORY|O_CLOEXEC) — the nsmgr resolves
   only the scheme part and dups the scheme-root capability.
2. openat(root_fd, reference, flags) — the kernel routes straight to the
   provider; the nsmgr is out of the data path.

With this, a busy/slow provider can no longer stall unrelated opens
through the nsmgr's single request loop.
This commit is contained in:
2026-07-31 00:02:28 +09:00
parent a359fb6155
commit 2fa1aac513
+17 -3
View File
@@ -589,10 +589,24 @@ pub fn getns() -> Result<usize> {
pub fn open<T: AsRef<str>>(path: T, flags: usize) -> Result<usize> {
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<T: AsRef<str>>(
fd: usize,