Po pierwsze , nie jesteś sam w zagadkach dotyczących tego rodzaju problemów.
Nie ogranicza się to tylko do tmpfs
problemu, o którym wspominano w
NFSv4 .
Jeśli aplikacja odczytuje „dziury” w rzadkim pliku, system plików konwertuje puste bloki na „prawdziwe” bloki wypełnione zerami i zwraca je do aplikacji.
Kiedy md5sum
próbuje skanować plik, jawnie decyduje się to zrobić w
kolejności sekwencyjnej , co ma sens w oparciu o to, co próbuje zrobić md5sum.
Ponieważ w pliku znajdują się zasadniczo „dziury”, ten sekwencyjny odczyt spowoduje (w niektórych sytuacjach), że operacja kopiowania podczas zapisu spowoduje wypełnienie pliku. To powoduje głębszy problem związany z tym, czy fallocate()
implementowane w systemie plików jest obsługiwane FALLOC_FL_PUNCH_HOLE
.
Na szczęście nie tylko to tmpfs
obsługuje, ale istnieje mechanizm „wykopywania” dziur z powrotem.
Za pomocą narzędzia CLI fallocate
możemy z powodzeniem wykryć i ponownie wykopać te dziury.
Zgodnie z man 1 fallocate
:
-d, --dig-holes
Detect and dig holes. This makes the file sparse in-place, without
using extra disk space. The minimum size of the hole depends on
filesystem I/O block size (usually 4096 bytes). Also, when using
this option, --keep-size is implied. If no range is specified by
--offset and --length, then the entire file is analyzed for holes.
You can think of this option as doing a "cp --sparse" and then
renaming the destination file to the original, without the need for
extra disk space.
See --punch-hole for a list of supported filesystems.
fallocate
działa jednak na poziomie plików, a kiedy pracujesz md5sum
na urządzeniu blokowym (żądając sekwencyjnych odczytów), masz do czynienia z dokładną przerwą między tym, jak fallocate()
powinien działać syscall. Widzimy to w akcji:
W działaniu na podstawie Twojego przykładu widzimy:
$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ONTGAS8L06
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ONTGAS8L06/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ sudo md5sum /dev/loop0
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 102400 /tmp/tmp.ONTGAS8L06/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ONTGAS8L06/sparse100M
Teraz ... to odpowiada na twoje podstawowe pytanie. Moje ogólne motto brzmi: „stań się dziwny”, więc kopałem dalej ...
$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ZcAxvW32GY
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 516 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 512 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51 /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
Widać, że tylko akt wykonywanialosetup
zmienia rozmiar pliku rozrzedzony. Staje się to więc interesującą kombinacją tmpfs
przecinania się mechanizmu HOLE_PUNCH fallocate
i urządzeń blokowych.