Linux DMA-BUF Fence Handoffs: An Exported sync_file Is a Snapshot, Not a Reservation
A graphics context exports a DMA-BUF fence, waits successfully, and still overlaps newer work submitted by another context. The exported object did not promise to track future submissions. It captured the relevant fence state at export time, leaving a coordination problem across the later submit and import steps.
This article pins the Linux v6.12 DMA-BUF synchronization UAPI and its kernel implementation. The example is a hypothetical embedded camera, GPU and display integration whose drivers support the selected interfaces. It is not a device test or a general cache-maintenance procedure.
Name the three operations separately
The UAPI describes an interoperability sequence for explicit and implicit synchronization. First, export a sync_file using DMA_BUF_IOCTL_EXPORT_SYNC_FILE with flags matching the intended access. Next, submit work that waits on the exported dependency and produces a completion fence. Finally, import that completion through DMA_BUF_IOCTL_IMPORT_SYNC_FILE so subsequent implicitly synchronized users can observe it.
The export is a snapshot. It allows waiting later on the fence set selected now. It does not reserve exclusive access to the buffer, and it does not keep adding future dependencies to the previously returned object.
The import publishes the new completion dependency into the DMA-BUF’s synchronization state. Publishing it after submission is an intentional part of this bridge, but the complete three-step sequence is not atomic. The UAPI explicitly assigns userspace responsibility for preventing intervening submissions or fence additions when ordering relies on this sequence.
Expose the unprotected interval
Suppose existing writer work is represented by fence F0. Context A intends to write the buffer and exports the relevant current dependencies. Before A has imported its own completion, context B submits conflicting work and publishes fence F1.
A’s previously exported snapshot still represents the dependencies captured earlier. Completion of F0 does not establish completion of F1, because B’s new fence was not in that snapshot. If A submits using only that dependency and no other ordering mechanism, the snapshot alone cannot prove that A and B’s accesses are serialized.
Importing A’s completion later does not retroactively insert B’s work into A’s already-chosen wait set. This is the specific failure to find in a trace: identify export, competing submission and completion import as distinct events rather than collapsing them into one operation called “synchronize buffer.”

Set flags from the intended buffer access
For export, DMA_BUF_SYNC_READ without DMA_BUF_SYNC_WRITE selects dependencies on current writers. A new read may coexist with other reads. An export containing DMA_BUF_SYNC_WRITE selects current readers and writers, because a new write conflicts with both. Setting both flags has the same export waiting effect as write alone.
For import, read-only flags publish a read fence. Later implicitly synchronized writes wait for that fence, while later reads do not. Importing with the write flag publishes a write fence that subsequent implicitly synchronized accesses wait on, whether they read or write.
These flags describe the work’s use of the buffer. They do not describe the direction in which a file descriptor moves between processes. A component that receives a descriptor but writes the image still needs write semantics.
Coordinate every relevant submitter
The protected coordination interval must cover export through successful publication of the submitted work’s completion fence. A shared application lock can serve that design only when every relevant submission and fence-publication path participates in the same protocol.
A mutex private to one process does not automatically exclude another process, an independent graphics context or a driver path outside that agreement. If all users cannot participate, the integration needs another supported coordination arrangement. Repeating export until the result happens to be signaled does not eliminate a competitor’s ability to submit afterward.
The kernel implementation reinforces the boundary: export obtains a fence representation and creates a sync_file; import separately locks the reservation object while adding fences. No kernel lock is retained across the intervening userspace rendering submission. The ioctls are also conditional on CONFIG_SYNC_FILE in this version, so availability must be established for the deployed kernel.
Include failed publication in the design
If submission succeeds but completion import fails, work may already be active without the intended dependency visible to later implicit users. Treat that as an incomplete handoff requiring the application’s supported recovery policy. Do not release coordination and assume a failed import cancelled the submitted work.
A proposed review should exercise a competitor between export and import, read versus write usage, and an import failure after successful submission. Record which participants are covered by the coordination mechanism and which are excluded from the design.
Fence completion, CPU cache preparation and visible presentation answer different questions. DMA_BUF_IOCTL_SYNC does not supply the missing cross-context exclusion, and this article makes no cache or scanout guarantee. No fence or device operation was executed. Acceptance requires a supported submission protocol that closes this specific snapshot window for every participating user.