A successful buffered write() does not generally mean that the new file data has already reached non-volatile storage. On Linux, the common buffered I/O path places file data in the page cache, marks the affected cache state dirty, and lets storage I/O occur later.

That separation is central to normal filesystem I/O. Memory absorbs application writes at CPU-accessible speed, while the kernel can schedule backing-device traffic independently. The result improves flexibility and can reduce immediate storage stalls, but it also creates a boundary between syscall completion and persistence.

Buffered writes normally enter the page cache

The page cache is the primary interface between normal file I/O and Linux filesystems. Reads can be served from cached file data, and ordinary buffered writes update cached file contents rather than bypassing memory and issuing a synchronous device operation for every syscall.

Modern kernel code manages page-cache memory in folios. When buffered file data changes, the relevant cache state becomes dirty. Dirty state records that the in-memory file contents differ from the copy represented by backing storage.

This does not make the write incomplete from the application’s syscall perspective. A write() can return successfully once the kernel has accepted the data into the buffered I/O path, subject to the filesystem and error conditions involved. Storage persistence is a separate event.

The distinction also means that a burst of application writes can accumulate dirty memory before all corresponding storage operations finish.

Writeback moves dirty file data toward storage

Linux writeback finds dirty page-cache data and sends it through the filesystem and block I/O stack toward the backing device. Writeback can start in the background, under dirty-memory pressure, or as part of an explicit synchronization request.

Kernel VM controls expose thresholds that influence this process. For example, background dirty limits can cause flusher activity to begin before dirty memory grows without bound. A process generating writes can also encounter throttling when dirty memory reaches stronger limits.

These controls are resource-management policy, not a promise that every write() immediately generates a matching device command. The kernel is free to group and schedule buffered work according to filesystem, VM, and block-layer behavior.

Writeback also has its own in-progress state. A folio that is being sent toward storage is not equivalent to one whose persistence has already been confirmed through every relevant layer.

fsync() establishes a stronger boundary

Applications that require a durability point use synchronization operations rather than treating successful buffered writes as persistence evidence. fsync() asks the kernel to synchronize file state required for the operation and wait for the relevant I/O to complete.

The exact work depends on the filesystem and storage stack. File data may need writeback, filesystem metadata may need ordering or persistence, and the block layer may need to account for volatile device caches.

This is especially important because many storage devices can acknowledge writes before data reaches non-volatile media. Linux provides cache-flush and Force Unit Access mechanisms that filesystems can use when enforcing data-integrity ordering on devices with volatile write-back caches.

The application-visible durability contract therefore crosses several layers. Page-cache writeback is one part of the path; filesystem ordering and device cache behavior are also relevant.

Dirty-memory limits control pressure, not transaction semantics

Linux exposes settings such as dirty_background_bytes, dirty_background_ratio, dirty_bytes, and dirty_ratio. They influence when background writeback starts and when tasks producing dirty data may be forced to participate in or wait for writeback.

Those settings can materially change workload behavior. A system that permits more dirty memory can absorb a larger burst before storage becomes the dominant limiter. A tighter limit can expose backing-device throughput sooner.

They do not turn buffered writes into filesystem transactions. They also do not replace application-level synchronization where a program requires a defined persistence point.

Periodic writeback is similarly a maintenance mechanism. Old dirty data can be selected for background writeout, but periodic activity is not a substitute for an explicit durability operation at a point where application correctness depends on persistence.

Memory reclaim can trigger writeback

Clean page-cache memory can often be reclaimed because its contents can be read again from the backing file. Dirty file data is different: discarding it before synchronization would lose modifications that exist only in memory.

Memory pressure can therefore lead to writeback as the VM works to make dirty cache state reclaimable. This connects filesystem I/O latency with memory pressure even when an application did not issue a synchronization syscall at that moment.

The effect is workload-dependent. Dirtying rate, available memory, filesystem behavior, backing-device throughput, and VM policy all affect when a writer encounters pressure.

Direct I/O follows a different cache path

The buffered-I/O model should not be generalized to every file operation. O_DIRECT can bypass the page cache for supported I/O, subject to filesystem and alignment constraints. Memory-mapped file writes also interact with page-cache state through a different application interface.

Even outside the page cache, completion and durable media state can remain distinct when volatile caches or asynchronous storage layers are involved. Bypassing the page cache removes one buffering layer; it does not automatically erase every persistence boundary below the filesystem.

Completion and persistence are separate system events

Buffered I/O works because Linux can acknowledge application writes before all backing-storage work has finished. Dirty page-cache state records the gap, writeback advances that state toward storage, and synchronization operations provide stronger persistence boundaries when software needs them.

For performance analysis, this means syscall latency and storage latency are not interchangeable measurements. For correctness, it means a successful buffered write() and a completed durability operation carry different guarantees. The distinction is a property of the I/O stack, not an exceptional case.