Skip to content

feat(libkernel): implement sceKernelFdatasync - #2129

Merged
oneandonlydean merged 3 commits into
boykopovar:mainfrom
sktharunbalaji13-cmd:contrib/scekernel-fdatasync
Oct 10, 2026
Merged

oneandonlydean merged 3 commits into
boykopovar:mainfrom
sktharunbalaji13-cmd:contrib/scekernel-fdatasync

Conversation

@sktharunbalaji13-cmd

@sktharunbalaji13-cmd sktharunbalaji13-cmd commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

What

Implement the missing sceKernelFdatasync libkernel export (NID 30Rh4ixbKy4), which is imported by Dying Light 2 (PPSA02262). The implementation uses _commit on Windows and fdatasync on POSIX, following the existing sceKernelFsync implementation pattern.

Add regression coverage for successful synchronization and invalid POSIX file descriptors. The related open PR #1620 implements a distinct fdatasync_nid_postfix export with a different NID, so it does not overlap with this change.

Tested

Windows/MinGW Release:

  • cmake --build build --target guest_filesystem_tests — passed.
  • ctest --test-dir build -R "^guest_filesystem$" --output-on-failure — 1/1 passed.
  • Verified sceKernelFdatasync is exported and the repository NID helper returns 30Rh4ixbKy4.

WSL/Linux Release:

  • cmake --build build-libs --target guest_filesystem_tests — passed.

  • ctest --test-dir build-libs -R '^guest_filesystem$' --output-on-failure — 1/1 passed.

  • Verified the exported symbol; both valid-descriptor and invalid-descriptor assertions passed.

  • Confirmed the regression before the fix via a link failure for the missing export.

  • git diff --check — passed.

  • The full test suite and Dying Light 2 runtime were not tested.

Checklist

  • Based on current upstream main; no duplicate PR implements this export/NID.
  • One topic per PR; implementation and regression tests only.
  • No code comments or silent stubs added.
  • No notes, reports, images, or third-party code added.
  • Generic behavior; not title-specific.
  • Depends on: none.
  • AI-assisted: yes (OpenCode).

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Does Dying Light 2 (PPSA02262) stop at sceKernelFdatasync on main? Please add the log line where it stops; an import alone isn't enough for a new export. Also, sceKernel* functions return SCE error codes, so a bad descriptor should give 0x80020009, not -1 (the test at GuestFilesystem.cpp:158 should check that).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 9, 2026
@sktharunbalaji13-cmd
sktharunbalaji13-cmd force-pushed the contrib/scekernel-fdatasync branch from 517eb1e to 8734b92 Compare October 10, 2026 07:52
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 10, 2026
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Progress report (de5e541 → 57be03a)

➖ System libraries: 84.52% (+0.0%, +1 implemented functions)

✅ 1 implemented
Library Name
libkernel sceKernelFdatasync

@klosixgaming-arch

Copy link
Copy Markdown
Contributor

Independent validation on Windows

Built and ran the PR head 8734b923 on my own box:

  • Windows 11 Pro (26200), WinLibs MinGW-w64 GCC 15.2.0 (r7), Release, BUILD_TESTING=ON.

Results:

  • guest_filesystem_tests PASSES (exit 0). libkernel.prx exports sceKernelFdatasync (verified with nm: T sceKernelFdatasync).
  • The bundled GuestFont.cpp change: guest_font_tests PASSES (exit 0) after the font .prx DLLs are present in the tests dir.

Rigor check (is the test real?): I removed the sceKernelFdatasync implementation from Stdio.cpp, rebuilt, and confirmed guest_filesystem_tests fails to link — undefined reference to 'sceKernelFdatasync' — then restored it → PASS. So the new test genuinely requires the new export rather than passing unconditionally. This matches the "link failure for the missing export" base regression noted in the PR.

One concern — scope / "one topic per PR": this PR bundles two unrelated changes:

  1. the sceKernelFdatasync feature + its GuestFilesystem.cpp test, and
  2. an unrelated font-test isolation change in GuestFont.cpp (the PR's head commit is even titled "test(font): isolate system font failure case").

The author checked "One topic per PR", but these are two distinct topics. I'd suggest splitting the font-test change into its own PR so review/rollback stay clean.

Honest limits of what I verified:

  • On Windows I verified the valid-fd == 0 path and the export. The invalid-fd == -1 assertion is inside #ifndef _WIN32, so it does not run on Windows — I could not verify that path here.
  • I did not test the Linux/POSIX fdatasync path (no Linux here) or the Dying Light 2 title (no game/ROM).

Written with AI assistance.

@sktharunbalaji13-cmd
sktharunbalaji13-cmd force-pushed the contrib/scekernel-fdatasync branch from 8734b92 to 36bc921 Compare October 10, 2026 11:35
@sktharunbalaji13-cmd

Copy link
Copy Markdown
Contributor Author

Status update after the rebase and scope cleanup.

Title evidence (Dying Light 2, PPSA02262) — reported by @tv7 in #1794 (comment):

  • Clean main: the loader stops at FAIL: unresolved ELF import 30Rh4ixbKy4 from libkernel.prx.
  • With this change: that import resolves, and execution advances to FAIL: unresolved ELF import -q-vbO859Tw from libSceVideoOut.prx.

This is evidence the import blocker advances past 30Rh4ixbKy4; it is not a claim that the title becomes playable (12 further imports remain unresolved).

Scope — the PR now contains only core/libs/prx/libkernel/File/src/Stdio.cpp and core/libs/tests/GuestFilesystem.cpp. The bundled test(font) change was dropped, since main now carries that fix (SetFontDirectory in GuestFont.cpp), which had caused a redefinition build error.

Behavior — sceKernelFdatasync maps native failures through SceErrorFromErrno(errno) and returns 0 on success, matching the neighbouring sceKernel* file calls; the closed-descriptor assertion expects 0x80020009.

Tests — guest_filesystem passes on Windows (MinGW-w64 GCC 15.2.0) and on Linux.

@orishamir

Copy link
Copy Markdown
Contributor

Built the PR (head 36bc9214) merged with current main and probed the new export against a guest socket: sceKernelFdatasync(socket) returns 0x80020009, while fdatasync_nid_postfix(socket) on the same descriptor returns -1 with errno 22, because the POSIX export checks GuestSockets::FirstDescriptor first and this one does not. The EBADF comes from the host rejecting 0x10000000 as an fd, so it is accidental; on Windows the same call reaches _commit and the UCRT invalid-parameter handler in CrashReport.cpp before returning.

Suggest moving the guard and the host call into sceKernelFdatasync and having fdatasync_nid_postfix wrap it, the way fsync_nid_postfix wraps sceKernelFsync.

Probe (linked like guest_filesystem_tests, Linux):

const int s = socket_nid_postfix(2, 1, 0);        // 0x10000000
sceKernelFdatasync(s);                             // -> 0x80020009
fdatasync_nid_postfix(s);                          // -> -1, guest errno 22
sceKernelFdatasync(0x7fffffff);                    // -> 0x80020009

Not run on Windows. AI-assisted.

Add the guest socket descriptor guard to sceKernelFdatasync before any
native syscall, matching the existing sceKernelFchmod pattern. This
prevents high guest socket descriptors (e.g. 0x10000000) from reaching
the Windows CRT _commit, which would trigger the invalid-parameter
handler, and ensures the correct SCE error is returned on all platforms.

Refactor fdatasync_nid_postfix to delegate to sceKernelFdatasync via
PosixResult, removing the duplicated socket guard and native syscall.

Extend GuestFilesystem tests to cover:
- sceKernelFdatasync on a valid guest socket returns SCE EINVAL (0x80020016)
- sceKernelFdatasync on a closed guest socket returns SCE EBADF (0x80020009)
- sceKernelFdatasync on a high invalid descriptor (0x7fffffff) returns SCE EBADF
- closed-ordinary-descriptor tests now run on Windows (verified _commit on
  a closed descriptor returns EBADF without provoking the CRT handler)
@sktharunbalaji13-cmd

Copy link
Copy Markdown
Contributor Author

Thanks @orishamir for catching the guest-socket descriptor issue — that was a real bug.

The fix is in 57be03a4:

  • sceKernelFdatasync now checks GuestSockets::FirstDescriptor before any native syscall. An open guest socket returns SCE EINVAL (0x80020016); a closed or invalid guest socket returns SCE EBADF (0x80020009). This prevents high guest descriptors from reaching _commit on Windows (which would trigger the UCRT invalid-parameter handler).
  • fdatasync_nid_postfix now delegates to sceKernelFdatasync through PosixResult, so the socket guard and error mapping live in one place — no duplicated logic.

The targeted guest_filesystem_tests passed on Windows/MinGW and Linux/WSL, including the new assertions for a valid socket (EINVAL), a closed socket (EBADF), and a high invalid descriptor like 0x7fffffff (EBADF). The full test suite and Dying Light 2 were not tested.

@orishamir

Copy link
Copy Markdown
Contributor

Confirmed on 57be03a merged with current main (Linux): guest_filesystem_tests passes, and the probe from above now gives sceKernelFdatasync(socket) = 0x80020016 for an open guest socket and 0x80020009 for a bad descriptor, matching fdatasync_nid_postfix. Nothing further from me on this one.

@oneandonlydean
oneandonlydean merged commit 2ece83f into boykopovar:main Oct 10, 2026
14 checks passed
adriadam10 pushed a commit that referenced this pull request Oct 11, 2026
Dying Light 2 (PPSA02262) imports sceKernelAioSetParam (9WK-vhNXimw) from
its eboot. In #1794 tv7 reported on main b5f5362 + #2129 (2026-10-10):

  FAIL: unresolved ELF import -q-vbO859Tw from libSceVideoOut.prx

with "12 other imports are still unresolved on `main`. In the eboot,
`-q-vbO859Tw`, `GTfJ64qFCPw`, `vwtVpHQKelI` (no known names),
`sceKernelAioSetParam` and `sceNpWebApi2GetMemoryPoolStats`." The import
is observed; its position in the loader queue after the nameless NIDs is
predicted.

The function fills one SceKernelAioSchedulingParam (five 4-byte fields,
20 bytes): Orbital cc408367 tools/ida/db_types.json:1103, SharpProspero
5dfdb4b0 Interop/Kernel/KernelAio.cs ("Sets every field of param at
once") and ampr_emu cfa85df3 ps5/include/sce/_fs.h agree on
(param, schedulingWindowSize, delayedCountLimit, enableSplit, splitSize,
splitChunkSize). No source gives an error code, so a null struct and
values outside SharpProspero's maximums (window and delayed count 0..128,
split flag 0 or 1, sizes up to 0x1000000) throw. The engine does not use
the settings, as sceKernelAioInitializeImpl ignores its struct; this is
recorded in TechnicalDebt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit e45a2b9)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants