Linux Writeback Errors: A Successful fsync Retry Does Not Erase the Earlier Failure
A second fsync() returning zero does not erase an earlier reported writeback failure. Linux can report an error through an observer cursor and then advance that cursor, so a later check sees no new error even though the application still lacks proof that its earlier commit succeeded.
This review pins Linux v6.12’s error-sequence and file-writeback implementation, with the inspected Linux man-pages 6.19 fsync(2) contract. It uses a source-grounded observation model. No storage fault, disk-full condition, filesystem sync or target write was executed.
Keep the first failure in the application record
Imagine a logger preparing generation G17. Its writes were accepted, but the synchronization step reports an error. The application should preserve that failure, the affected generation and whether it already acknowledged G17 to a consumer.
If the next synchronization call succeeds, record that later result as a separate observation. Do not overwrite G17’s unresolved state with a generic “storage healthy” flag. The later success alone does not identify which earlier bytes reached storage or establish that the failed commit was repaired.
This distinction is about evidence, not a claim that recovery is impossible. A reviewed recovery procedure may rewrite or reconstruct a generation and verify a new commit. That procedure needs its own identity and outcome rather than borrowing certainty from a quiet error check.
Understand the watcher cursor
The v6.12 errseq documentation describes shared error state observed through individual sampled cursors. A check-and-advance operation reports a newly observed error and moves that observer forward. It is not an exact count of all failures or a ledger assigning each failure to one application record.
In the v6.12 filemap implementation, file_check_and_advance_wb_err() compares the mapping’s error sequence with file->f_wb_err. When unchanged, it returns zero. When a new error is observed, it advances the file object’s cursor under its lock and returns the error.
The comment ties this to errors since the previous check, or since opening when there was no earlier check. That explains why repeated checks can differ without any repair operation occurring between them.

Compare independent opens with duplicates
Use two hypothetical independent opens, A and B, established before a qualifying error. Each has its own file object and observation cursor. In the source model, A can observe the new error and advance its cursor while B still has an unobserved error relative to its own cursor.
A later check by A can therefore return zero while B’s first relevant check reports the error. That difference does not mean storage failed again between the two observations. The observers were at different positions.
Now replace B with a duplicate of A’s descriptor. Duplicates refer to the same open file description and therefore the same relevant file-object cursor. A different integer descriptor number does not create an independent observer. Record open-description ownership when two software components share or duplicate handles.
The sequence above is an explanatory model, not a universal promise about every filesystem’s exact reporting path. The error source and filesystem still matter.
Do not infer record ownership from EIO
The fsync manual explains that a synchronization error can concern writes through another descriptor on the same file. Since Linux 4.13, writeback reporting reaches descriptors that may have written affected data; many local filesystems report more broadly than filesystems that track writer provenance precisely.
Thus, a result on A is important evidence but does not uniquely identify A’s last record as the failed write. Preserve the application’s own generation and write ledger, and state the uncertainty instead of manufacturing byte-level attribution from the error number.
A loop that keeps retrying until zero and then discards the original error destroys precisely the evidence needed to decide what must be recovered. Bound retries according to the actual operation and retain every consequential failure.
Keep filesystem-wide synchronization in its own scope
The v6.12 syncfs implementation synchronizes the filesystem associated with the descriptor and checks a superblock error sequence through f_sb_err. That is a different scope from a single file’s writeback cursor.
A filesystem-wide result is not a per-record receipt for G17. Do not substitute syncfs() merely to obtain a reassuring status from another observation boundary. The implementation and error scope should remain explicit in the diagnostic record.
Review recovery without injecting a real fault
A proposed application-level fixture can feed the logger a synchronization failure followed by a zero result. Require G17 to remain unresolved until an explicit recovery path supplies new completion evidence. Add independent-open and shared-description observer models to test that diagnostics do not invent an extra failure count.
Later storage qualification belongs on a recoverable development setup with an approved fault plan. For this document, the deliverable is a commit-status ledger that preserves the first failure and distinguishes it from subsequent observer results. That is the minimum needed to avoid turning a consumed error notification into a false durability claim.