Skip to content

Remove dead code and simplify code introduced during sidecar migration - #284

Merged
jserv merged 8 commits into
sysprog21:mainfrom
henrybear327:sysroot/redundant-work
Aug 14, 2026
Merged

Remove dead code and simplify code introduced during sidecar migration#284
jserv merged 8 commits into
sysprog21:mainfrom
henrybear327:sysroot/redundant-work

Conversation

@henrybear327

@henrybear327 henrybear327 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Follow up improvement effort to improve code introduce in #256


Summary by cubic

Removes sidecar-era paths and cuts per-lookup work in casefold and sysroot resolution. Old: each component copied prefixes, re-derived realpath() and object types, and rebuilt resolver outputs; new: probe components in place, reuse ATTR_CMN_OBJTYPE, skip redundant realpath() and concatenations, and treat fully typed walks as containment proofs.

  • Probe components in place: append candidates to out and restore its terminator. out doubles as probe scratch; do not overlap out with guest_path or base_host_prefix.

  • Reuse object types from the probe: record leaf_type_known, leaf_is_link, and all_types_known. Run fstatat/faccessat only when types are unknown. host_component_spelling exposes link-ness to the NO_XDEV walker.

  • Skip the sysroot containment recheck for a fully typed walk; keep it for listing-answered components, dot components, and byte-exact paths.

  • Canonicalize the sysroot once and read _Atomic fold/canonical flags. Avoid per-call realpath() and skip sysroot snapshots for relative paths.

  • Remove unread resolver outputs and duplicate sysroot+lookup concatenations; rely on the seed buffer.

  • Make the walk report optional in casefold_resolve_at; pass NULL when only the verdict or out is needed.

  • Move the UTF-8/UTF-16 budget oracles into tests; drop casefold_utf16_units from casefold.h.

  • Fixes

    • Withdraw type info on readdir fallback so callers do not skip required fstatat checks.
    • Bounds-check getattrlistat stored-name replies; prevent an overlong append from leaving a trailing /.
    • Make the escape fallback strict: on broken preconditions, return an error rather than guess a spelling.

Written for commit 2c1a26c. Summary will update on new commits.

Review in cubic

@henrybear327
henrybear327 marked this pull request as draft August 11, 2026 19:24
@henrybear327
henrybear327 marked this pull request as ready for review August 11, 2026 19:25
@henrybear327
henrybear327 force-pushed the sysroot/redundant-work branch from add8997 to 8162e84 Compare August 11, 2026 19:43
@henrybear327
henrybear327 marked this pull request as draft August 11, 2026 20:08
@henrybear327
henrybear327 marked this pull request as ready for review August 11, 2026 21:50
cubic-dev-ai[bot]

This comment was marked as resolved.

@henrybear327
henrybear327 force-pushed the sysroot/redundant-work branch from 8162e84 to ba5dacb Compare August 11, 2026 22:45
@henrybear327

henrybear327 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator Author

@henrybear327
henrybear327 marked this pull request as draft August 11, 2026 23:14
@henrybear327
henrybear327 force-pushed the sysroot/redundant-work branch 2 times, most recently from 9aef30d to ff2fa48 Compare August 13, 2026 12:14
@henrybear327
henrybear327 marked this pull request as ready for review August 13, 2026 12:14
cubic-dev-ai[bot]

This comment was marked as resolved.

@henrybear327
henrybear327 marked this pull request as draft August 13, 2026 12:27
Two computations ran on every translation that reached them, and
nothing read their results.
path_check_relative_sysroot_containment() filled a 4 KiB buffer with
the reconstructed absolute guest path for callers that need it, but one
caller passes NULL and the other never reads the buffer again. Both
byte-exact resolver arms then re-concatenated the sysroot and the
lookup into a buffer the seed had already spelled from the same
operands, nothing on those arms having rebased the lookup.

The two spellings differ in one case: under --sysroot /, the snprintf
produced a doubled separator, the prefix and the clamped lookup each
carrying a slash. Every consumer either passes the buffer through
realpath() or special-cases the one-byte prefix, so no behavior depends
on that extra byte.
Four things in the walk's per-component loop had no reader or no
reachable caller.

resolve_component() reported presence through @present beside its
verdict, and the two never diverged: presence was set on exactly the
paths that return PROBE_EXACT, so callers test the verdict instead.
probe_exact() guarded its @is_link out-param against a NULL that no
caller passes. The escape fallback in resolve_component() cannot run:
path_component_copy() delivers a non-empty, slash-free name of at most
CASEFOLD_GUEST_NAME_MAX bytes into a statically sized buffer that
casefold.h proves large enough, and its retry could only repeat the
failure it handled. That arm now returns PROBE_ERROR rather than guess
a spelling.

casefold_resolve_at() required a walk report, so four of its six
callers declared a casefold_walk_t only to satisfy the signature. The
report becomes optional; three of those callers pass NULL here, and the
fourth keeps its struct because a later commit reads it.
casefold_utf16_units, and the UTF-8 validator standing behind it, have
no production caller: the escape decision already covers ill-formed
UTF-8 through its byte >= 0x80 rule, and the unit budgets are enforced
by static assert. The host lane's budget check is the only consumer.

Move both there. Inside the codec, that check compares the production
arithmetic against itself. In the test the counter is a second
implementation, so a codec change that breaks the unit budget shows up
as a disagreement between the two instead of being mirrored into both
sides at once.
proc_sysroot_casefold_enabled(), which backs every casefold_active()
call, took sysroot_lock several times per translation to read a flag
decided once at startup, and re-published to a forked child, before any
vCPU thread issues a syscall. No other state is kept consistent with
it, so the lock provided ordering that nothing requires. Make the flag
_Atomic and state the published-once invariant where it is set.
Two per-call computations re-derived values fixed at configuration
time. sysroot_seed_host_path() took the sysroot snapshot, and with it a
mutex acquisition, before testing whether the path is even absolute, so
every relative-path syscall performed a snapshot it then discarded; the
absolute-path test now runs first. sysroot_path_is_contained()
re-derived realpath(sysroot) although proc_set_sysroot() canonicalizes
the sysroot once; it now copies that snapshot, and falls back to the
per-call derivation only for a sysroot that did not resolve then.

The flag recording which of those two cases holds is read without the
lock, so it is _Atomic, matching the fold flag beside it.
Each component copied the whole accumulated prefix into a private
4 KiB buffer before appending its candidate, twice when the literal
probe missed, which is the rescan the running length exists to avoid.
Append into the output buffer and restore the terminator instead: the
per-component cost drops from a copy of the prefix to a copy of the
component bytes. A candidate that does not fit still reports
ENAMETOOLONG, an escape never being shorter than the literal it stands
for.

The restore also runs when the append itself fails. The separator is
written before the length check that rejects the candidate, so without
the restore an over-long component would leave a trailing slash in the
caller's buffer.
Every component probe requests ATTR_CMN_OBJTYPE, and the answer was
discarded and then derived again: the NO_XDEV walker re-asked with
fstatat per component, and the walk re-confirmed a resolved leaf with
faccessat.

Record what the probe established in the walk report and gate both
calls on it. The recheck stays wherever the walk cannot answer: the
readdir fallback, whose listing carries no type and so withdraws
whatever the probe before it learned, and the byte-exact arm, which
runs no walk.

The surviving fstatat in the NO_XDEV walker now runs only where the
walk left link-ness unknown, and the restructure carries its errno rule
across unchanged: ENOENT is itself an answer, nothing there being able
to be a link, while any other errno leaves link-ness undecided and
fails the walk. Mount classification depends on that walk, so it must
not cross a component it could not type.
Every successful in-sysroot lookup called realpath() on a path the walk
had just spelled, to prove the result lands inside the sysroot. A walk
that answered every component's object type has already proven it: no
symlink can hide in a path where every component was typed, so the host
spelling cannot resolve anywhere but under the prefix it was built
from.

Record that condition in the walk report as all_types_known and skip
the re-derivation when it holds. It does not hold for the readdir
fallback, whose listing carries no type, or for the byte-exact arm,
which runs no walk, and the create resolver's parent keeps its
unconditional check: a mkdir may have just materialized it.

The host lane pins the flag from both sides as a regression guard: the
behavior arrives correct, so the checks cannot be observed red against
this commit, but deleting the fallback's withdrawal makes the
listing-answered case fail, which is the wrong answer this guard exists
to catch.
@henrybear327
henrybear327 force-pushed the sysroot/redundant-work branch from ff2fa48 to 2c1a26c Compare August 13, 2026 12:52
@henrybear327
henrybear327 marked this pull request as ready for review August 13, 2026 14:18

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 8 files

Re-trigger cubic

@jserv
jserv merged commit 693ce4f into sysprog21:main Aug 14, 2026
21 checks passed
@henrybear327
henrybear327 deleted the sysroot/redundant-work branch August 14, 2026 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants