Secara sederhana, ini sederhana dd
:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
Itu membaca seluruh file, dan menulis seluruh konten kembali ke sana.
Untuk hanya menulis lubang itu sendiri, pertama-tama Anda harus menentukan di mana lubang itu berada. Anda dapat melakukannya dengan menggunakan baik filefrag
atau hdparm
:
filefrag:
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1048575: 187357696.. 188406271: 1048576:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188406272: last,eof
sparsefile: 2 extents found
hdparm:
# hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 1498861568 1507250175 8388608
6442450944 1605633024 1614021631 8388608
Contoh file ini, seperti yang Anda katakan, 10G
berukuran 2G
berlubang. Ini memiliki dua luasan, penutup pertama 0-1048575
, kedua 1572864-2621439
, yang berarti bahwa lubang itu 1048576-1572864
(dalam blok ukuran 4k, seperti yang ditunjukkan oleh filefrag
). Info yang ditunjukkan oleh hdparm
adalah sama, hanya ditampilkan secara berbeda (tingkat pertama mencakup 8388608
sektor 512-byte mulai dari 0 sehingga 0-4294967295
byte, sehingga lubang 4294967296-6442450944
dalam byte.
Perhatikan bahwa Anda mungkin akan diperlihatkan jauh lebih luas jika ada fragmentasi. Sayangnya, tidak ada perintah yang menunjukkan lubang secara langsung, dan saya tidak tahu yang melakukannya, jadi Anda harus menyimpulkannya dari offset logis yang ditampilkan.
Sekarang, mengisi 1048576-1572864
lubang itu dengan dd
seperti yang ditunjukkan di atas, dapat dilakukan dengan menambahkan yang sesuai (identik) seek
/ skip
nilai dan count
. Perhatikan bahwa bs=
diadaptasi untuk menggunakan 4k
sektor - sektor seperti yang digunakan oleh di filefrag
atas. (Untuk bs=1M
, Anda harus menyesuaikan nilai pencarian / lewati / hitung untuk mencerminkan 1M
blok berukuran).
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
Meskipun Anda dapat mengisi lubang dengan /dev/zero
alih - alih membaca lubang file itu sendiri (yang juga akan menghasilkan angka nol), tetap lebih aman untuk membaca dari yang lain sparsefile
sehingga Anda tidak akan merusak data Anda jika Anda mendapat offset yang salah.
Dalam versi yang lebih baru GNU dd
, Anda dapat tetap menggunakan blocksize yang lebih besar dan menentukan semua nilai dalam byte:
dd if=sparsefile of=sparsefile conv=notrunc bs=1M \
iflag=skip_bytes,count_bytes oflag=seek_bytes \
seek=4294967296 skip=4294967296 count=$((-4294967296+6442450944))
filefrag
setelah menjalankan itu:
# sync
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1572863: 187357696.. 188930559: 1572864:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188930560: last,eof
sparsefile: 2 extents found
Karena fragmentasi, itu masih dua tingkat. Namun, offset logis menunjukkan bahwa kali ini, tidak ada lubang, sehingga file tidak lagi jarang.
Secara alami, dd
solusi ini adalah pendekatan yang sangat manual untuk berbagai hal. Jika Anda membutuhkan ini secara teratur, akan mudah untuk menulis sebuah program kecil yang mengisi kekosongan tersebut. Jika sudah ada sebagai alat standar, saya belum pernah mendengarnya.
Lagipula ada alat, fallocate
sepertinya berfungsi, setelah mode:
fallocate -l $(stat --format="%s" sparsefile) sparsefile
Namun pada akhirnya dalam kasus XFS, meskipun tidak mengalokasikan area fisik untuk file ini, sebenarnya tidak nol. filefrag
menunjukkan luasan seperti yang dialokasikan, tetapi tidak tertulis.
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
Ini tidak cukup baik jika tujuannya adalah untuk dapat membaca data yang benar langsung dari perangkat blok. Ini hanya menyimpan ruang penyimpanan yang dibutuhkan untuk penulisan di masa mendatang.
cat sparsefile 1<> sparsefile
. Anda mungkin dapat menggunakanfallocate
Linux untuk menghindari keharusan menulis byte NUL itu jika yang Anda inginkan adalah ruang yang dialokasikan.fallocate
. Memiliki--dig-holes
tetapi tidak ada--fill-holes
. Namun, tampaknya berfungsi cukup baik ketika Anda menentukan ukurannya. Saya akan mengedit jawaban saya.fallocate
memiliki-z
yang dapat digunakan di Linux 3.14 dan di atas pada ext4 dan xfs (Anda harus menjalankannya dengan-o
dan-l
untuk semua bagian yang jarang saya kira).-z
tidak menyimpan data Anda jika Anda salah offset, jadi saya akan tetap didd
sana ...