Skip to content

Research notes / Linux I/O contracts

io_uring: completion is not a durable commit

14 October 2026 / Source review and illustrative ordering model

Submitting a write followed by fsync does not, by itself, order them. The sync can run too early. Durable acknowledgment requires a dependency, complete write results and successful synchronization. [2]

Three boundaries, three different answers

io_uring exchanges requests and results through shared submission and completion rings. A submission result is not the write's byte count. Inspect the request's completion queue entry: its res carries the operation result or a negative error number. Do not interpret arrival alone as success. [1] [7]

For a write, compare the returned byte count with the requested length. A partial result leaves work unfinished. Use deliberate offsets: the write helper warns that asynchronous access to a shared current file offset can behave unpredictably unless serialized. [5]

For synchronization, io_uring_prep_fsync defaults to file-integrity synchronization; IORING_FSYNC_DATASYNC selects the narrower fdatasync contract. Preparing an SQE does not execute it. [4]

A chain is not a ring-wide barrier

Documented ordering scope; none of these flags repairs a failed write. [3]
PatternWhat is orderedBoundary
Adjacent write, syncNo explicit dependency.Queue position is insufficient.
Write with IO_LINKNext request starts after this one completes.Only this chain; submit it together.
Sync with IO_DRAINEarlier requests finish first; later ones wait.Same ring, not other rings or processes.
Wait, then submit syncApplication checks relevant write completions first.Track every write in the intended commit.

Linked requests serialize a dependency chain, not unrelated work. A normal link breaks on an error or unexpected result; unstarted successors receive -ECANCELED. IO_HARDLINK preserves links across completion errors, but not all submission failures. A successful later sync therefore cannot certify that every predecessor wrote its intended data. [2]

IO_DRAIN waits for completion; it does not itself flush storage. There is another API trap: IOSQE_CQE_SKIP_SUCCESS and IOSQE_IO_DRAIN must not be mixed in one ring, even on different requests, under the documented contract. Avoid a completion-suppression optimization that invalidates the ordering design. [2]

Why completion order alone is weak evidence

Our deliberately simplified model enumerates three events: a full write completes, synchronization starts, synchronization completes. Sync completion must follow its start. All calls succeed; the file already exists, with no competing writer. These are logical examples, not captured kernel traces.

The model checks a sufficient ordering condition, not whether bytes happened to persist.
Event orderWrite completed before sync began?
write-complete > sync-start > sync-completeYes
sync-start > write-complete > sync-completeNot established
sync-start > sync-complete > write-completeNot established

In the middle case, write completion precedes sync completion but follows sync start. That observation alone is insufficient. Missing the dependency does not prove data loss: storage may have persisted the data anyway. The three rows are not equally likely outcomes and cannot yield a failure probability.

The dependency-free model prints its assumptions and traces when run with Node.js. Tests reject duplicate, missing and causally impossible events and check the counterexample.

What the FAST paper actually measures

Joshi and colleagues' FAST 2024 paper studies an NVMe passthrough path built on io_uring commands. Section 2.2 separates batching, polling and chaining. Its efficiency evaluation compares character-device and block-device paths, not durable file commits. Section 7.1 uses unbuffered random reads on an Intel Optane P5800X; Table 3 lists Linux 6.2 and fio 3.35. [8]

The reported peak-IOPS improvement is not evidence that write-plus-sync ordering is unnecessary, nor a portable speedup for a database commit. The evaluation also varies kernel configuration, including mitigations. We did not reproduce it and do not recommend disabling security protections for benchmark scores.

Review the acknowledgment, not just the queue

Identify the intended write set, request IDs, offsets, expected lengths, dependency scope, every completion result and the sync target. A file sync does not necessarily persist its containing directory entry. Creation and replacement protocols need their own directory treatment. [6]

Ordering is not rollback or multi-file atomicity. After an error, preserve the failure context instead of treating another successful sync as proof of repair. See fsync error recovery and durable rename. These examples assume ordinary one-shot file writes with visible completions; multishot operations and cancellation protocols need separate analysis.

Sources and limits

Primary-source API review using liburing 2.9 manuals, the current io_uring_enter manual and FAST 2024 sections 2.2 and 7.1; executable enumeration of an explicitly simplified event-order model. No kernel execution experiment, power-loss test, workload benchmark or paper reproduction. Model traces illustrate missing guarantees, not failure frequencies. Synchronization assumes the underlying storage honors its contract.

  1. liburing: io_uring(7), result reporting and shared rings.
  2. liburing: io_uring_enter(2), IORING_OP_FSYNC, linking and CQE_SKIP_SUCCESS constraints.
  3. liburing 2.9: io_uring_sqe_set_flags(3), chain and drain scope.
  4. liburing 2.9: io_uring_prep_fsync(3), fsync and fdatasync semantics.
  5. liburing 2.9: io_uring_prep_write(3), explicit offsets and result handling.
  6. Linux man-pages: fsync(2), error and directory persistence boundaries.
  7. liburing: io_uring_submit(3), submission return value.
  8. Kanchan Joshi, Anuj Gupta, Javier Gonzalez, Ankit Kumar, Krishna Kanth Reddy, Arun George, Simon Lund and Jens Axboe. I/O Passthru: Upstreaming a flexible and efficient I/O Path in Linux. FAST 2024, pp. 107-121; sections 2.2 and 7.1, Table 3.

Checked 14 October 2026. liburing 2.9 is an explicit review target, not a claim about the latest release.