Rename pathname mengubah entri direktori sementara file descriptor yang sudah terbuka tetap merujuk ke objek dasar yang sama. Linux renameat2() menambahkan kebijakan pada pembaruan namespace tersebut: pemanggil dapat menolak penggantian, menukar dua nama yang sudah ada, atau meminta whiteout untuk operasi union filesystem. Kebijakan ini dijalankan sebagai bagian dari operasi rename, bukan sebagai pemeriksaan terpisah di userspace.
Interface ini khusus Linux. Argumen flags bernilai nol memberikan perilaku renameat(), sedangkan flag nonnol menambahkan semantik Linux yang juga bergantung pada dukungan filesystem yang di-mount.
Rename mengubah nama, bukan referensi objek yang sudah terbuka
Rename yang berhasil memindahkan sebuah nama dari satu entri direktori ke lokasi lain, sesuai aturan filesystem. Hard link lain menuju inode yang sama tetap menjadi link ke objek tersebut. File descriptor yang sebelumnya dibuka melalui pathname lama juga tetap valid; descriptor merujuk pada open file description dan file dasar, bukan pada janji bahwa pathname awal akan tetap tersedia.
Perbedaan ini membuat rename dapat berfungsi sebagai titik commit namespace. Sebuah proses dapat menyiapkan objek dengan satu nama lalu memublikasikannya dengan nama lain. Penggantian namespace yang atomik tidak berarti pembaca lama berpindah objek: proses yang telah membuka target lama dapat terus memakai descriptor yang sudah dimilikinya.
Penggantian rename biasa juga memiliki properti visibilitas yang spesifik. Jika tujuan sudah ada dan penggantian diizinkan, tujuan diganti secara atomik sehingga lookup pathname secara konkuren tidak melihat interval saat nama tujuan hilang. Properti ini berlaku pada operasi entri direktori. Properti tersebut tidak dengan sendirinya menjamin persistensi setelah kehilangan daya; durabilitas penyimpanan memerlukan filesystem dan operasi sinkronisasi terkait untuk memenuhi kontrak terpisah.
RENAME_NOREPLACE menghapus race antara pemeriksaan dan rename
Urutan userspace yang mula-mula memeriksa keberadaan tujuan lalu menjalankan rename biasa memiliki race. Proses lain dapat membuat tujuan setelah pemeriksaan tetapi sebelum rename. Rename terakhir kemudian dapat mengganti objek yang tidak pernah terlihat oleh pemeriksaan awal.
RENAME_NOREPLACE memasukkan kondisi tersebut ke dalam operasi rename:
int rc = renameat2(old_dirfd, "staged",
new_dirfd, "current",
RENAME_NOREPLACE);Jika current sudah ada, operasi gagal dengan EEXIST alih-alih menggantinya. Kondisi keberadaan dan mutasi namespace dengan demikian menjadi satu operasi yang dimediasi kernel dari sudut pandang pemanggil.
Flag ini tidak mencadangkan tujuan setelah kegagalan. Percobaan berikutnya mengevaluasi namespace kembali. Flag ini juga bukan compare-and-swap umum atas isi file atau metadata inode; kondisinya secara khusus menyatakan bahwa pathname tujuan belum boleh ada.
Dukungan filesystem merupakan bagian dari kontrak. Linux menambahkan dukungan RENAME_NOREPLACE pada berbagai filesystem secara bertahap, sehingga perangkat lunak yang menargetkan beragam kernel dan filesystem perlu memperlakukan dukungan sebagai properti lingkungan, bukan properti universal setiap mount Linux.
RENAME_EXCHANGE menukar dua nama yang sudah ada
RENAME_EXCHANGE secara atomik menukar objek yang dinamai oleh pathname sumber dan tujuan. Kedua nama harus sudah ada. Berbeda dari urutan tiga rename biasa dengan nama sementara, exchange tidak mengekspos state namespace perantara yang muncul pada urutan tersebut.
Kedua entri dapat menamai tipe objek yang berbeda sesuai semantik operasi yang terdokumentasi. Jaminan utamanya berlaku pada pasangan entri direktori: setelah berhasil, setiap nama merujuk ke objek yang sebelumnya dicapai melalui nama lainnya.
Exchange tidak menggabungkan state objek dan tidak mengubah descriptor yang sudah terbuka. Descriptor yang dibuka melalui nama A sebelum exchange tetap merujuk ke objek awalnya setelah nama A diikat ulang ke objek yang sebelumnya berada di nama B. Kode yang menggabungkan lookup pathname dengan descriptor berumur panjang perlu memisahkan dua bentuk identitas tersebut.
RENAME_EXCHANGE tidak dapat digabungkan dengan RENAME_NOREPLACE. Kedua kebijakan menyatakan kondisi tujuan yang bertentangan: exchange mensyaratkan kedua nama sudah ada, sedangkan no-replace mensyaratkan tujuan belum ada.
Directory file descriptor menstabilkan jangkar lookup
Seperti renameat(), renameat2() menerima directory file descriptor terpisah untuk path relatif sumber dan tujuan. oldpath relatif diresolusikan dari olddirfd, sedangkan newpath relatif diresolusikan dari newdirfd. Path absolut mengabaikan directory descriptor yang bersangkutan.
Mekanisme ini menghapus ketergantungan pada current working directory proses untuk lookup relatif tersebut. Namun, mekanisme ini tidak menyediakan kontrol resolusi yang lebih kuat seperti pada openat2(): renameat2() tidak memiliki RESOLVE_BENEATH, RESOLVE_NO_SYMLINKS, atau argumen kebijakan resolusi yang setara. Penamaan relatif terhadap direktori dan pembatasan traversal path adalah mekanisme yang berbeda.
Aplikasi yang memerlukan batas direktori tepercaya tetap harus menangani komponen path dan perilaku symbolic link secara terpisah. Directory descriptor yang stabil menjadi jangkar resolusi relatif, tetapi API rename tidak mengubah string path relatif arbitrer menjadi traversal yang dibatasi capability.
Batas mount tetap menjadi kendala keras
Rename beroperasi di dalam satu mounted filesystem. Jika sumber dan tujuan berada pada mounted filesystem yang berbeda, Linux melaporkan EXDEV. Hal ini tetap berlaku meski filesystem dasar yang sama dipasang pada beberapa mount point.
Akibatnya, rename tidak dapat menjadi primitive publikasi atomik lintas lokasi penyimpanan arbitrer. Fallback yang menyalin data ke filesystem tujuan lalu menghapus sumber merupakan protokol berbeda dengan state kegagalan yang berbeda. Selama fallback semacam itu, kedua salinan dapat tersedia, hanya satu dapat tersedia, atau metadata dapat berbeda tergantung urutan operasi dan kegagalan.
Properti atomik rename karena itu harus dilekatkan pada operasi rename yang benar-benar berhasil, bukan digeneralisasi ke command atau library yang mengemulasikan pemindahan lintas batas mount.
RENAME_WHITEOUT mengikat rename dengan state namespace overlay
RENAME_WHITEOUT tersedia untuk implementasi union dan overlay filesystem. Whiteout menandai nama pada source layer sebagai tersembunyi sementara objek hasil rename dibuat terlihat di tujuan pada writable layer. Linux menjalankan pembuatan whiteout dan rename secara atomik ketika operasi berhasil.
Di luar konteks union atau overlay, representasi whiteout Linux tampak sebagai character device dengan nomor device {0,0}. Penggunaan flag ini memerlukan CAP_MKNOD, dan dukungan filesystem juga diperlukan. Kondisi tersebut menjadikan flag ini mekanisme infrastruktur, bukan opsi manajemen file yang portabel.
RENAME_WHITEOUT tidak dapat digabungkan dengan RENAME_EXCHANGE. Semantiknya menyatakan penggantian sumber dengan whiteout selama rename satu arah, berbeda dari pertukaran dua entri yang sudah ada.
Perubahan namespace atomik lebih sempit daripada publikasi durable
renameat2() dapat membuat kondisi namespace dan mutasinya tidak terpisahkan pada interface system call: menolak target yang sudah ada, menukar dua nama, atau mengikat rename dengan pembuatan whiteout. Hal ini menutup race yang muncul ketika kebijakan tersebut dirangkai dari operasi pathname terpisah.
Batasnya tetap sempit. Descriptor yang terbuka mempertahankan referensi objek melintasi rename, perpindahan lintas mount tidak termasuk dalam jaminan, dukungan flag dapat bergantung pada filesystem, dan mutasi namespace yang berhasil bukan jaminan durabilitas dengan sendirinya. Desain yang memakai rename sebagai titik commit memerlukan kontrak terpisah untuk sinkronisasi data, persistensi direktori, kepercayaan resolusi path, dan pemulihan setelah kegagalan remote filesystem.