Diposting oleh Chris Siebenmann , Administrator Sistem Unix di University of TorontoDari waktu ke waktu, sesuatu yang aneh terjadi dalam pekerjaan saya yang membuat saya berpikir. Bahkan jika tidak segera jelas kesimpulan yang mengikuti. Baru-baru ini saya menyebutkan bahwa kami menemukan bug di GNU Tar, dan kisah bagaimana ini terjadi adalah salah satu kasusnya.
Untuk server file cadangan, kami menggunakan Amanda dan GNU Tar. Seiring waktu, kami terkadang memiliki masalah yang agak jarang terjadi di mana tar menjadi gila ketika membuat cadangan sistem file dengan direktori
/var/mail
, menghasilkan sejumlah besar output. Biasanya proses ini berjalan hingga tak terbatas dan harus membunuh tempat sampah; dalam kasus lain, itu masih berakhir dengan mengeluarkan terabyte (s) data yang tampaknya terkompresi dengan sempurna. Ketika saya sekali lagi menemukan file tar raksasa, saya memeriksanya - dan menemukan bahwa itu sebagian terdiri dari nol byte, yang benar-benar tidak disukai oleh tim pengujian
tar -t
, setelah semuanya kembali normal.
(Karena ini, saya bertanya-tanya apakah byte nol muncul secara alami pada orang-orang di kotak surat. Ternyata
menemukan byte nol dalam file teks tidak begitu sederhana dan ya, mereka ada di sana).
Kami baru-baru ini memindahkan sistem file dari
/var/mail
ke server file Linux baru di bawah Ubuntu 18.04 dan karenanya beralih ke versi GNU Tar yang lebih baru dan lebih standar daripada di mesin OmniOS. Kami berharap ini akan menyelesaikan masalah kami, tetapi kejadian yang sama segera terjadi. Kali ini GNU Tar bekerja pada mesin Ubuntu, di mana saya sangat mengenal semua alat debugging yang tersedia, jadi saya memeriksa proses
tar
sedang berjalan. Pengujian menunjukkan bahwa
tar
menghasilkan aliran
read()
tanpa akhir menghasilkan 0 byte:
read(6, "", 512) = 0 read(6, "", 512) = 0 [...] read(6, "", 512) = 0 write(1, "\0\0\0\0\0"..., 10240) = 10240 read(6, "", 512) = 0 [...]
lsof
mengatakan file deskriptor 6 adalah kotak surat orang lain.
Menggunakan
apt-get source tar
saya mengunduh kode sumber dan mulai mencari panggilan sistem
read()
di dalamnya yang tidak memeriksa penyelesaian file. Setelah memeriksa beberapa tingkat pengalamatan tidak langsung, saya menemukan tempat yang jelas di mana tampaknya cek semacam itu dihilangkan, yaitu dalam fungsi
sparse_dump_region
dari file
sparse.cs . Dan kemudian saya teringat sesuatu.
Beberapa bulan yang lalu,
kami mengalami masalah NFS di Alpine . Saat mengerjakan bug ini, saya melacak proses Alpine dan memperhatikan, di antaranya, bahwa ia menggunakan
ftruncate()
untuk mengubah ukuran kotak surat; kadang-kadang memperluas mereka, sementara membuat bagian file yang jarang sampai mengisinya, dan mungkin kadang-kadang mengompresnya. Ini tampaknya bertepatan dengan situasi saat ini: area jarang terhubung, dan mengurangi ukuran file menggunakan
ftruncate()
menciptakan situasi di mana tar tiba-tiba menemui penyelesaian file.
(Ini bahkan menjelaskan mengapa tar kadang-kadang dikembalikan; jika email baru tiba-tiba tiba di kotak surat kemudian, ia kembali ke ukuran yang diharapkan, dan tar tidak lagi menemukan penghentian file yang tidak terduga).
Saya sedikit kacau di GDB dengan simbol debugging Ubuntu dan kode sumber paket tar yang saya terima, dan mampu mereproduksi kesalahan, meskipun agak berbeda dari teori asli saya. Ternyata
sparse_dump_region
tidak mengatur ulang area jarang pada file, tetapi me-reset area non-jarang (tentu saja), dan digunakan untuk semua file (jarang atau tidak) jika Anda menjalankan tar dengan argumen -
--sparse
. Dengan demikian, kesalahan sebenarnya adalah bahwa
jika Anda menjalankan GNU Tar dengan argumen --sparse
dan file dikompresi saat sedang dibaca, tar tidak dapat dengan benar menangani akhir file yang diterima lebih awal dari yang diharapkan . Jika file tumbuh lagi, tar mengembalikan.
(Kecuali ketika file jarang di akhir dan dikompresi hanya di tempat ini. Dalam hal ini, semuanya beres).
Saya berpikir bahwa semua sama saya dapat memeriksa bertahun-tahun yang lalu di server file OmniOS kami. Ada beberapa cara untuk melacak panggilan sistem dari program dan analognya, dan saya dapat menemukan dan melihat kode sumber versi GNU Tar saya dan menjalankannya dengan debugger OmniOS (walaupun kami tampaknya tidak memiliki GDB yang diinstal di sana), dan seterusnya. Tapi saya tidak melakukannya. Sebaliknya, kami mengangkat bahu dan melanjutkan. Saya perlu memindahkan sistem file di bawah Ubuntu sehingga saya akan menggerakkan jari saya dan mencari tahu masalahnya.
(Ini bukan hanya tentang alat dan lingkungan; kami secara otomatis mengasumsikan bahwa OmniOS memiliki beberapa versi lama GNU Tar, yang tidak masuk akal untuk diselidiki, karena tentu saja masalahnya diselesaikan dalam versi yang lebih baru).
PS: Mungkin, sebagai perbaikan cepat, kami cukup melarang Amanda menggunakan opsi tar -
--sparse
saat mencadangkan. Kotak surat tidak boleh jarang, dan jika ini terjadi,
kami masih memampatkan cadangan sistem file , sehingga semua nol byte ini terkompresi dengan baik.
PPS: Saya tidak mencoba melaporkan bug ke pengembang GNU Tar, karena saya menemukannya hanya pada hari Jumat, dan universitas sedang liburan musim dingin sekarang. Jangan ragu untuk melakukannya sebelum saya.