Pemanggilan rename() yang berhasil dapat mengganti pathname tujuan yang sudah ada tanpa memperlihatkan keadaan perantara ketika nama tujuan tersebut hilang. Proses yang melakukan resolusi terhadap tujuan akan melihat directory entry lama atau penggantinya, dengan tetap tunduk pada batasan filesystem dan mount.

Transisi namespace atomik tersebut lebih sempit daripada sejumlah sifat yang sering diasosiasikan dengan penggantian file. Operasi ini tidak membuat write sebelumnya menjadi durable, tidak memaksa metadata direktori ke penyimpanan stabil, dan tidak membatalkan file descriptor yang sudah merujuk ke file yang diganti.

Unit atomiknya adalah perubahan namespace

Pathname diresolusikan melalui directory entry menuju objek filesystem. Mengganti config.new ke atas config dengan rename() mengubah asosiasi namespace untuk nama tujuan.

if (rename("config.new", "config") == -1) {
    perror("rename");
}

Ketika sumber dan tujuan berada pada filesystem yang sama dan didukung serta operasi berhasil, proses lain yang mencari config tidak perlu melewati keadaan akibat operasi ini ketika config tidak memiliki target. Jika config sebelumnya ada, penggantian menghapus namanya sebagai bagian dari operasi rename yang sama.

Sifat ini berguna untuk pola publikasi karena pembaca yang membuka tujuan berdasarkan nama tidak melihat file tujuan yang baru tersalin sebagian. File pengganti dapat disiapkan di bawah nama lain sebelum namespace dialihkan.

File descriptor yang sudah ada mempertahankan referensi objeknya

Mengganti pathname tidak mengarahkan ulang file descriptor yang sebelumnya dibuka melalui pathname tersebut.

Misalkan proses A membuka config dan mempertahankan descriptor. Proses B kemudian melakukan rename file lain ke atas config. Lookup pathname baru dapat mencapai pengganti, sedangkan descriptor milik proses A tetap merujuk ke open file description lama dan objek file yang mendasarinya.

File lama karena itu dapat tetap diakses setelah directory entry sebelumnya hilang. Penyimpanannya baru dapat direklamasi setelah link count dan referensi terbuka yang relevan mengizinkannya.

Hal ini memisahkan identitas pathname dari identitas objek terbuka. Penggantian atomik memengaruhi resolusi namespace berikutnya; operasi tersebut tidak menulis ulang referensi yang sudah ada.

Perpindahan lintas filesystem berada di luar operasi

rename() tidak menyediakan perpindahan atomik antara mounted filesystem yang berbeda. Di Linux, rename yang melintasi mount point gagal dengan EXDEV, bahkan ketika kedua mount memakai tipe filesystem yang sama.

Aplikasi yang merespons EXDEV dengan menyalin data lalu menghapus sumber telah mengubah semantik operasinya. Penyalinan mencakup banyak read dan write, sehingga observer berpotensi melihat keadaan tujuan perantara kecuali skema temporary-file dan publikasi terpisah digunakan pada filesystem tujuan.

Atomicity rename dari kernel berlaku pada operasi namespace di dalam batas filesystem yang mendukungnya, bukan pada transfer arbitrer antar-path.

Visibilitas atomik bukan crash durability

Rename dapat atomik bagi observer pathname yang berjalan bersamaan tetapi tetap rentan terhadap crash sebelum metadata mencapai penyimpanan stabil.

Untuk penggantian persisten, urutan yang relevan umumnya mencakup menulis file baru, menyinkronkan datanya sesuai kebutuhan, melakukan rename, lalu menyinkronkan direktori induk ketika kontrak filesystem dan durability mengharuskan pembaruan direktori bertahan setelah crash.

Jaminan persistensi yang tepat bergantung pada filesystem, storage stack, mount option, dan antarmuka sistem yang digunakan. Atomicity menjawab apakah observer konkuren dapat melihat transisi namespace perantara. Durability menjawab apakah state yang selesai bertahan setelah kegagalan dan restart. Keduanya merupakan sifat yang berbeda.

Mengganti tujuan tidak menggabungkan isi file

rename() mengubah nama; operasi ini tidak menggabungkan objek sumber dan tujuan. Jika tujuan ada dan penggantian diizinkan, directory entry miliknya digeser oleh objek sumber.

Karena itu, temporary file yang sudah disiapkan berbeda secara material dari mengedit tujuan secara in-place. Write in-place mempertahankan identitas objek tujuan dan dapat memperlihatkan isi yang sedang berubah kepada pembaca yang berbagi objek tersebut. Publikasi berbasis rename membuat objek terpisah terlebih dahulu, lalu mengubah objek mana yang diresolusikan oleh nama tujuan.

Pembaca dengan descriptor lama dapat terus melihat objek lama, sementara pembaca yang membuka setelah pergantian dapat melihat objek baru. Hasilnya menyerupai serah-terima versi pada batas namespace, bukan mutasi satu objek file bersama.

Pemeriksaan metadata dapat mengalami race sebelum rename

Urutan yang memeriksa tujuan lalu memanggil rename() biasa tidak mencadangkan pathname di antara kedua operasi tersebut. Proses lain dapat mengubah namespace setelah pemeriksaan.

Linux menyediakan flag renameat2() untuk kasus yang memerlukan semantik operasi lebih kuat. RENAME_NOREPLACE meminta kegagalan ketika tujuan sudah ada. RENAME_EXCHANGE menukar dua pathname secara atomik alih-alih mengganti satu dengan yang lain.

Flag tersebut memindahkan kondisi ke dalam operasi rename dan menghindari jendela check-then-act terpisah untuk sifat yang dinyatakannya. Dukungan tetap bergantung pada kernel dan filesystem.

Penempatan direktori menentukan batas publikasi

Temporary file untuk penggantian atomik biasanya dibuat pada filesystem yang sama dengan tujuan akhir. Menempatkan temporary file pada direktori sementara generik dapat tanpa sengaja melintasi batas mount dan membuat rename terakhir gagal dengan EXDEV.

Membuat objek sementara di direktori tujuan juga membuat direktori induk eksplisit untuk penanganan persistensi. Permission, ownership, mode, extended attribute, dan metadata lain tetap memerlukan perlakuan khusus karena mengganti directory entry tidak otomatis menyalin metadata dari objek yang digeser.

Batas utamanya tetap presisi: rename dapat menyediakan satu transisi namespace atomik. Isi file harus sudah berada dalam keadaan yang diinginkan sebelum publikasi, referensi terbuka yang ada tetap valid, dan persistensi terhadap crash memerlukan kontrak sinkronisasi tersendiri.