Files
xenia-rs/audit-runs/phase-c11-1-access-recent-fix/fix.diff
MechaCat02 ef93a4fa14 handoff: VSync/event-wedge fixes + iterate 2.A–2.BC research notes
Source changes (dormant parity infra, retained from iterate 2.AI/2.AO):
- xenia-kernel/exports.rs: nt_create_event manual_reset polarity +
  related event wiring
- xenia-gpu/mmio_region.rs: D1MODE_VBLANK_VLINE_STATUS hardcode parity

Also lands the audit-runs/ analysis notes (.md/.txt/.json digests) for the
iterate 2.x VSync/0x10e8/0x1004 wedge investigation. Raw trace dumps
(.jsonl/.gz/.csv/.stdout) and agent worktrees (.claude/) are gitignored as
regenerable local artifacts — see memory + HANDOFF for the running findings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 07:19:08 +02:00

106 lines
4.4 KiB
Diff

Phase C+11.1 — `cache:/access` / `cache:/recent` dir-vs-file fix
================================================================
File: crates/xenia-kernel/src/exports.rs
Function: open_cache_file
Hunk 1: replace the post-existing-file-wins block with a
disposition-gated mkdir + STATUS_OBJECT_NAME_NOT_FOUND on miss.
Pre-fix (Phase C+11 HEAD):
let host_exists_as_dir = host_path.is_dir();
let host_exists_as_file = host_path.is_file();
let is_dir_open = host_exists_as_dir
|| (!host_exists_as_file && !want_non_dir && want_dir);
if is_dir_open {
// For non-existent paths the guest wants us to create as a
// directory, mkdir-p; canary's HostPathDevice does the same
// when FILE_DIRECTORY_FILE is set on a kCreate disposition.
if want_dir && !host_path.exists() {
if let Err(e) = std::fs::create_dir_all(host_path) {
...STATUS_UNSUCCESSFUL...
}
}
// ... falls through to SUCCESS / handle alloc
Post-fix (Phase C+11.1):
let host_exists_as_dir = host_path.is_dir();
let host_exists_as_file = host_path.is_file();
let is_dir_open = host_exists_as_dir
|| (!host_exists_as_file && !want_non_dir && want_dir);
if is_dir_open {
// Phase C+11.1 — only create the host directory when the
// disposition is *create-capable*. Mirrors canary's
// `VirtualFileSystem::OpenFile` (virtual_file_system.cc:265-273):
// for `FileDisposition::kOpen`/`kOverwrite` on a non-existent
// path the function returns `X_STATUS_OBJECT_NAME_NOT_FOUND`
// *before* any `CreatePath` call — i.e. mkdir is never invoked
// on these dispositions. The pre-fix code (Phase C+11) called
// `create_dir_all` whenever `want_dir && !host_path.exists()`,
// so Sylpheed's cold-boot probes for `cache:/access`,
// `cache:/ignore`, `cache:/recent` (disp=1, opts=0x7) succeeded
// and produced spurious host directories. Canary instead
// returns NOT_FOUND, after which Sylpheed re-creates these as
// FILES via `disp=5` + `FILE_NON_DIRECTORY_FILE`.
//
// Create-capable dispositions (mkdir OK):
// 0 FILE_SUPERSEDE
// 2 FILE_CREATE
// 3 FILE_OPEN_IF
// 5 FILE_OVERWRITE_IF
// Non-create dispositions (must miss when path is absent):
// 1 FILE_OPEN
// 4 FILE_OVERWRITE
let disp_is_create_capable = matches!(
create_disposition,
FILE_SUPERSEDE | FILE_CREATE | FILE_OPEN_IF | FILE_OVERWRITE_IF
);
if !host_path.exists() {
if !disp_is_create_capable {
if handle_out != 0 {
mem.write_u32(handle_out, 0);
}
write_io_status_block(
mem,
io_status_block,
STATUS_OBJECT_NAME_NOT_FOUND as u32,
0,
);
tracing::info!(
"cache open (dir) MISS path={:?} disp={} opts={:#x} -> NOT_FOUND",
guest_path,
create_disposition,
create_options
);
return STATUS_OBJECT_NAME_NOT_FOUND;
}
// create-capable + want_dir → mkdir-p the directory.
if want_dir {
if let Err(e) = std::fs::create_dir_all(host_path) {
...STATUS_UNSUCCESSFUL...
}
}
}
// ... falls through to SUCCESS / handle alloc as before
Hunk 2 (tests): two new unit tests added in
crates/xenia-kernel/src/exports.rs after
`cache_top_level_manifests_create_as_files`:
- cache_open_directory_on_missing_path_returns_not_found
Loops over the three cold-probe paths Sylpheed actually emits
(cache:\\access, cache:\\ignore, cache:\\recent) and asserts
NtCreateFile + disp=1 + opts=0x7 returns NOT_FOUND, writes
handle=0, and leaves no host entry on disk.
- cache_disp5_after_disp1_miss_creates_file
Pins the canary two-call sequence: cold disp=1 returns NOT_FOUND;
immediately following disp=5 + opts=0x60 (FILE_NON_DIRECTORY_FILE)
succeeds and produces a host FILE.
LOC summary: ~30 added in open_cache_file (mkdir gate + NOT_FOUND
return branch + comments), ~6 removed (the unconditional mkdir
flow); ~88 lines of test code for the two new tests.