Tout d'abord, vous n'êtes pas seul à vous interroger sur ce genre de problèmes.
Cela ne se limite pas à, tmpfs
mais a été une préoccupation citée avec
NFSv4 .
Si une application lit des "trous" dans un fichier clairsemé, le système de fichiers convertit les blocs vides en "vrais" blocs remplis de zéros et les renvoie à l'application.
Lorsque md5sum
tente d'analyser un fichier, il choisit explicitement de le faire dans
un ordre séquentiel , ce qui a beaucoup de sens en fonction de ce que md5sum tente de faire.
Comme il y a fondamentalement des "trous" dans le fichier, cette lecture séquentielle va (dans certaines situations) entraîner une copie lors d'une opération d'écriture pour remplir le fichier. Cela entre alors dans un problème plus profond quant à savoir si ou non fallocate()
implémenté dans le système de fichiers prend en charge FALLOC_FL_PUNCH_HOLE
.
Heureusement, non seulement cela prend en tmpfs
charge mais il existe un mécanisme pour "creuser" les trous.
En utilisant l'utilitaire CLI, fallocate
nous pouvons réussir à détecter et refaire ces trous.
Selon 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
fonctionne au niveau du fichier et lorsque vous exécutez md5sum
sur un périphérique de bloc (demandant des lectures séquentielles), vous trébuchez sur l'écart exact entre la façon dont le fallocate()
syscall doit fonctionner. Nous pouvons le voir en action:
En action, en utilisant votre exemple, nous voyons ce qui suit:
$ 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
Maintenant ... cela répond à votre question de base. Ma devise générale est "devenir bizarre" alors j'ai creusé plus loin ...
$ 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
Vous voyez que le simple fait d' effectuer les losetup
modifications modifie la taille du fichier clairsemé. Cela devient donc une combinaison intéressante de l'endroit où tmpfs
le mécanisme HOLE_PUNCH fallocate
et les périphériques de bloc se croisent.