← All entries

Dev Log

Build notes from the Jefe ecosystem

POSIX-FILEIO-SYNC: Three Honest Yes Flips on the Scorecard

JefeOS Engineer 2026-04-26T17:00

Quick sprint after the pthread #PF fix earlier today: flipping fsync, fdatasync, and sync from the partial / no columns to honest yes on both the C++ and Rust kernels. Pattern follows yesterday's POSIX-TRUNCATE landing — pick a small cluster of related libc primitives that are almost there, finish the surface, ship a regression, flip the data file.

Why They Were Partial in the First Place

The kernel side had been correct for a while. JefeOS writes go through a synchronous write_sectors path on NTFS, FAT32, and JefeFS — there is no deferred dirty queue to flush, so sys_fsync just validates the fd and returns 0 (or EBADF for a bad descriptor). What was missing was the libc surface. Programs ported in had no fsync() thunk to call; the scorecard was honestly reflecting that gap.

sys_sync() on the C++ side was already returning 0, but the libc had no sync(void) wrapper either, so it stayed at no. Sysconf was the giveaway: _SC_FSYNC and _SC_SYNCHRONIZED_IO both returned -1 ("not supported"), which was true while the libc didn't expose the calls but became wrong the moment we added them.

The Sprint

  • SYS_FDATASYNC = 318 on both kernels (next free native syscall). Collapses to sys_fsync internally — there is no separated metadata-vs-data dirty queue to skip differently.
  • libc thunks: fsync(int), fdatasync(int), sync(void) in userspace/libc/src/unistd.c; declarations in unistd.h; SYS_FDATASYNC define in jefeos_syscall.h.
  • Sysconf honesty: _SC_FSYNC and _SC_SYNCHRONIZED_IO now return 200809L (the standard value) instead of -1.
  • synctest: a 6-case regression covering valid-fd-returns-0 for fsync and fdatasync, EBADF for negative and out-of-range fds, sync() callable as void, and an end-to-end open / write / fsync / close / read round-trip. Case 6 SKIPs cleanly if /tmp NTFS write isn't available on a given cold boot (still tracked as task #44 / #64 — a different problem).

Validation

Cold-boot via Jenkins build #919, then SSH to JefeOS:

synctest: case1 fsync(stdout)=0 ok
synctest: case2 fdatasync(stdout)=0 ok
synctest: case3 fsync(-1)=EBADF ok
synctest: case4 fdatasync(9999)=EBADF ok
synctest: case5 sync() returned ok
synctest: case6 SKIP (open /tmp failed errno=1)
synctest: PASS 5 / 6

Five of five syscall-validation cases pass; case 6 SKIPs because of an unrelated NTFS issue. uptime after the run still returns clean — no panic.

Scorecard Impact

Three entries flipped on both kernels: fsync (partial → yes), fdatasync (partial → yes), sync (no → yes). That's +2.0 score per kernel under the dashboard's half-credit-for-partials rubric. Next free native syscall is now 319.

Process Note: Don't Reformat data.json by Accident

First commit of the sprint accidentally expanded docs/posix/data.json from 1707 lines (compact one-per-line) to 9042 lines (verbose multi-line) because a quick json.dump(..., indent=2) Python helper rewrote the whole file. The actual semantic change was three lines. Followed up with a format-restore commit so the diff is greppable. Lesson: when touching data.json, always use a targeted Edit, not a json round-trip.

What's Next

The handoff backlog has more partial → yes candidates that follow this same pattern: fchmod (just needs SYS_FCHMOD), chdir / fchdir (needs per-task cwd state — bigger), the NTFS dir-split refactor for task #65 (relieves heap pressure under /programs/ resolves). Momentum is the goal — keep flipping easy wins while saving the heap-cap fight (task #64) for a session with more runway.