A successful rename() can replace an existing destination pathname without exposing an intermediate state in which that destination name is missing. Processes resolving the destination observe either the old directory entry or the replacement, subject to filesystem and mount constraints.
That atomic namespace transition is narrower than several properties often associated with file replacement. It does not make prior writes durable, does not force directory metadata to stable storage, and does not invalidate file descriptors that already refer to the replaced file.
The atomic unit is a namespace change
A pathname is resolved through directory entries to filesystem objects. Replacing config.new over config with rename() changes the namespace association for the destination name.
if (rename("config.new", "config") == -1) {
perror("rename");
}When source and destination are on the same supported filesystem and the operation succeeds, another process looking up config does not need to pass through a state created by this operation where config has no target. If config existed, the replacement removes its name as part of the same rename operation.
This property is useful for publication patterns because readers opening the destination by name avoid observing a partially copied destination file. The replacement file can be populated under another name before the namespace switch.
Existing file descriptors keep their object reference
Replacing a pathname does not retarget file descriptors that were opened through that pathname earlier.
Suppose process A opens config and retains the descriptor. Process B then renames a different file over config. New pathname lookups can reach the replacement, while process A’s descriptor still refers to the old open file description and underlying file object.
The old file can therefore remain accessible after its former directory entry disappears. Its storage is reclaimable only after the relevant link count and open references permit reclamation.
This separates pathname identity from open-object identity. Atomic replacement affects future namespace resolution; it does not rewrite existing references.
Cross-filesystem moves are outside the operation
rename() does not provide an atomic move between different mounted filesystems. On Linux, a rename that crosses mount points fails with EXDEV, even when both mounts use the same filesystem type.
Applications that respond to EXDEV by copying data and deleting the source have changed the operation’s semantics. A copy spans many reads and writes, so observers can potentially see intermediate destination state unless a separate temporary-file and publication scheme is used on the destination filesystem.
The kernel’s rename atomicity therefore applies to a namespace operation inside the filesystem boundary that supports it, not to an arbitrary path-to-path transfer.
Atomic visibility is not crash durability
A rename can be atomic to concurrent pathname observers while still being vulnerable to a crash before metadata reaches stable storage.
For persistent replacement, the relevant ordering commonly includes writing the new file, synchronizing its data as required, performing the rename, and synchronizing the containing directory when the filesystem and durability contract require the directory update to survive a crash.
The exact persistence guarantees depend on the filesystem, storage stack, mount options, and system interfaces in use. Atomicity answers whether concurrent observers can see an intermediate namespace transition. Durability answers whether completed state survives failure and restart. They are distinct properties.
Replacing a destination does not merge file contents
rename() changes names; it does not combine the source and destination objects. If the destination exists and replacement is permitted, its directory entry is displaced by the source object.
That makes a prepared temporary file materially different from editing the destination in place. In-place writes preserve the destination object’s identity and can expose changing contents to readers sharing that object. Rename-based publication creates a separate object first and then changes which object the destination name resolves to.
Readers with old descriptors can continue seeing the old object, while readers opening after the switch can see the new one. The result resembles version handoff at the namespace boundary rather than mutation of one shared file object.
Metadata checks can race before rename
A sequence that checks the destination and later calls ordinary rename() does not reserve the pathname between those operations. Another process can modify the namespace after the check.
Linux provides renameat2() flags for cases that need stronger operation-specific semantics. RENAME_NOREPLACE requests failure when the destination already exists. RENAME_EXCHANGE atomically exchanges two pathnames instead of replacing one with the other.
These flags move the condition into the rename operation, avoiding a separate check-then-act window for the property they express. Support still depends on the kernel and filesystem.
Directory placement defines the publication boundary
Temporary files used for atomic replacement are normally created on the same filesystem as the final destination. Placing a temporary file in a generic temporary directory can accidentally cross a mount boundary and turn the final rename into an EXDEV failure.
Creating the temporary object in the destination directory also makes the containing directory explicit for persistence handling. Permissions, ownership, mode, extended attributes, and other metadata still need deliberate treatment because replacing the directory entry does not automatically copy metadata from the displaced object.
The central boundary remains precise: rename can provide one atomic namespace transition. File contents must already be in the desired state before publication, existing open references remain valid, and crash persistence requires its own synchronization contract.