Skip to content

fix(libkernel): report NODEV and a per-socket inode from fstat on a socketpair end - #10621

Merged
oneandonlydean merged 4 commits into
boykopovar:mainfrom
Retr0G28:fix/socketpair-fstat-inode
Oct 26, 2026
Merged

oneandonlydean merged 4 commits into
boykopovar:mainfrom
Retr0G28:fix/socketpair-fstat-inode

Conversation

@Retr0G28

@Retr0G28 Retr0G28 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

What

fstat on a socketpair end reported st_dev and st_ino 0, which the debt entry recorded. FreeBSD 11's uipc_sense, the pru_sense of a local socket, sets st_dev to NODEV and st_ino to the socket's unp_ino. A socket gets its unp_ino from one global counter the first time it is sensed, skipping 0, and keeps it. dev_t and ino_t are 32-bit in FreeBSD 11, as in FileStat, so NODEV is 0xFFFFFFFF. Inet sockets use pru_sense_null, which leaves both 0.

GuestSockets::Stat now does the same for a socket of family AF_UNIX, which only socketpair creates. The socket gets a number from a counter under socketsMutex the first time it is stat'ed, and the number is kept in Socket. A dup shares the Socket, so it reports the same number, as it shares the struct socket on FreeBSD. The other fields are unchanged.

main added a sentence to the fstat on a guest socket debt entry saying a socketpair end reports st_dev and st_ino 0. It now names only what still differs: the number comes from a counter this process starts at 1, where FreeBSD's unp_ino is one counter for every local socket on the system, so the numbers differ from the console's. st_dev now matches.

Test: guest_socket_pair checks that both ends of a stream pair report st_dev 0xFFFFFFFF and a nonzero st_ino. The two ends must differ, a second fstat or sceKernelFstat must give the same number, and a dup of an end must report that end's number. An AF_INET socket still reports st_dev and st_ino 0.

Tested

Windows 11, WinLibs MinGW-w64 GCC 15.2.0 r7, CMake + Ninja, Release, -DBUILD_TESTING=ON, rebased on main 6cd36e6.

  • Before the rebase, on main a23f8fc: with main's Udp.cpp, guest_socket_pair fails (exit 0xc0000409 from the failed Require). With this PR it passes, and ctest -R "socket|sendfile|kqueue|poll" passes 39 of 39.
  • After the rebase: ctest -R "socket|recvmsg|sendfile|kqueue|^guest_poll$" passes 32 of 32 when run serially.
  • After merging main afc780e (head ada29c7): the same pattern passes 42 of 42 when run serially.
  • python tools/check_conventions.py --base origin/main reports no errors.
  • Not run on Linux or macOS, where the pair is a host AF_UNIX pair and the same code path runs. No title or homebrew run.

Overlap (tools/pr_overlap.py):

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The GuestSockets::Stat change and tests look consistent with the described AF_UNIX behavior: inode assignment occurs under socketsMutex, the Socket owns the value so dup shares it, and the AF_INET control preserves zeros. One coordination item remains in the PR body: it says #8344 adds a Socket member adjacent to this new inode field and whichever merges second needs a rebase, but the checklist says Depends on: none. CONTRIBUTING.md asks overlapping PRs to agree on order and declare that dependency. Please record the agreed order (or state that #8344 is the prerequisite) so reviewers and automation can track the shared insertion hunk. I have not independently run the Windows socket tests; hosted product build legs were skipped by eligibility.

@Retr0G28

Copy link
Copy Markdown
Contributor Author

@MarcZX10 Thanks. Both PRs are mine. The order is #8344 first, so the checklist now says Depends on: #8344 and the overlap note says so too. After #8344 merges I will merge main into this branch, keep both Socket members, and rerun guest_socket_pair and the socket tests.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The author has resolved the coordination item: #8344 is explicitly first, and this PR now declares Depends on: #8344 and says it will rebase and rerun guest_socket_pair after #8344 merges. I approve the reviewed implementation and tests at head c27cdcaf4cc1218a0679720ad6f3200645599255. The previously reviewed behavior remains consistent: inode assignment is protected by socketsMutex, lifetime is owned by the shared Socket (so dup retains identity), and AF_INET stats remain zero. Hosted eligibility/conventions/intake/labels pass; product checks were skipped. Windows socket test results are author-reported, not independently reproduced. The PR remains dependent on #8344 and should be revalidated after that rebase.

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 4630 docs/dev/debt/libkernel.md
PR 5021 core/libs/prx/libkernel/Socket/src/Udp.cpp
core/libs/tests/GuestSocketPair.cpp
docs/dev/debt/libkernel.md
PR 6149 docs/dev/debt/libkernel.md
PR 6936 docs/dev/debt/libkernel.md
PR 7088 core/libs/prx/libkernel/Socket/src/Udp.cpp
docs/dev/debt/libkernel.md
PR 7105 docs/dev/debt/libkernel.md
PR 7121 docs/dev/debt/libkernel.md
PR 7149 docs/dev/debt/libkernel.md
PR 7192 docs/dev/debt/libkernel.md
PR 7201 core/libs/prx/libkernel/Socket/src/Udp.cpp
PR 7447 docs/dev/debt/libkernel.md
PR 7509 docs/dev/debt/libkernel.md
PR 7804 docs/dev/debt/libkernel.md
PR 8605 core/libs/prx/libkernel/Socket/src/Udp.cpp
core/libs/tests/GuestSocketPair.cpp
docs/dev/debt/libkernel.md
PR 9156 docs/dev/debt/libkernel.md
PR 9199 docs/dev/debt/libkernel.md
PR 9284 docs/dev/debt/libkernel.md
PR 9293 docs/dev/debt/libkernel.md
PR 9297 docs/dev/debt/libkernel.md
PR 9302 docs/dev/debt/libkernel.md
PR 9389 docs/dev/debt/libkernel.md
PR 9557 docs/dev/debt/libkernel.md
PR 9566 docs/dev/debt/libkernel.md
PR 9575 docs/dev/debt/libkernel.md
PR 9713 core/libs/prx/libkernel/Socket/src/Udp.cpp
PR 9947 docs/dev/debt/libkernel.md
PR 9948 core/libs/prx/libkernel/Socket/src/Udp.cpp
PR 10442 docs/dev/debt/libkernel.md
PR 11085 docs/dev/debt/libkernel.md
PR 11215 docs/dev/debt/libkernel.md
PR 11223 core/libs/prx/libkernel/Socket/src/Udp.cpp
core/libs/tests/GuestSocketPair.cpp
docs/dev/debt/libkernel.md
PR 11264 docs/dev/debt/libkernel.md
PR 11267 docs/dev/debt/libkernel.md
PR 11341 docs/dev/debt/libkernel.md

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
…inode

# Conflicts:
#	core/libs/tests/GuestSocketPair.cpp
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@Retr0G28

Copy link
Copy Markdown
Contributor Author

Merged main f26434a to clear the same GuestSocketPair.cpp declaration conflict as #8344. The diff against main is unchanged. Head e7de2a5, Windows 11, GCC 15.2.0: 41 of 41 socket, recvmsg, sendfile, kqueue and poll tests pass when run serially.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
@oneandonlydean oneandonlydean self-assigned this Oct 25, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@Retr0G28 thanks for the socket inode work. #10621 conflicts with main in two places.

The Udp.cpp hunk is trivial: both std::uint32_t inode and main's new std::weak_ptr<Socket> peer stay in the struct. The debt entry for fstat on a guest socket in docs/dev/debt/libkernel.md needs your input, though.

Main added this sentence at the end of that entry: "A socketpair end reports st_dev and st_ino 0, where FreeBSD's uipc_sense reports NODEV and a per-socket number". Your PR now gives unix-family sockets a lazily assigned st_ino, so the st_ino 0 half is no longer true for them after your change.

Could you merge main and restate that sentence to what still differs from FreeBSD once your PR is in? For example, whether st_dev is still 0 and how the number differs from uipc_sense's. Please keep main's wording elsewhere in the entry, including sceKernelClose in the first bullet.

…inode

# Conflicts:
#	core/libs/prx/libkernel/Socket/src/Udp.cpp
#	docs/dev/debt/libkernel.md
@Retr0G28

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Merged main afc780e. In Udp.cpp both std::uint32_t inode and std::weak_ptr<Socket> peer stay in the struct. The fstat on a guest socket entry keeps main's wording, sceKernelClose included; only the last sentence changes.

After this PR, st_dev is NODEV (0xFFFFFFFF) as in uipc_sense, so it's no longer a gap. st_ino is a nonzero per-socket number assigned on the first fstat and kept, also as in uipc_sense. What still differs is where the number comes from, so the sentence now reads:

A socketpair end's st_ino comes from a counter this process starts at 1, where FreeBSD's uipc_sense uses one counter for every local socket on the system, so the numbers differ from the console's

Head ada29c7, Windows 11 (GCC 15.2.0): ctest -R "socket|recvmsg|sendfile|kqueue|^guest_poll$" passes 42 of 42 when run serially, and check_conventions.py passes. Depends on is now none, since #8344 has merged.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@oneandonlydean
oneandonlydean merged commit 9021e9b into boykopovar:main Oct 26, 2026
10 of 11 checks passed
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.

3 participants