Sur ma ext4
partition de système de fichiers, je peux exécuter le code suivant:
fs="/mnt/ext4"
#create sparse 100M file on ${fs}
dd if=/dev/zero \
of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2> /dev/null
#show its actual used size before
echo "Before:"
ls ${fs}/sparse100M -s
#setting the sparse file up as loopback and run md5sum on loopback
losetup /dev/loop0 ${fs}/sparse100M
md5sum /dev/loop0
#show its actual used size afterwards
echo "After:"
ls ${fs}/sparse100M -s
#release loopback and remove file
losetup -d /dev/loop0
rm ${fs}/sparse100M
qui donne
Before:
0 sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
0 sparse100M
Faire la même chose sur tmpfs qu'avec:
fs="/tmp"
les rendements
Before:
0 /tmp/sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
102400 /tmp/sparse100M
ce qui signifie essentiellement que quelque chose que je m'attendais à lire simplement les données, a fait "exploser le fichier" comme un ballon "?
Je m'attends à ce que cela soit dû à une prise en charge moins parfaite du fichier clairsemé dans le tmpfs
système de fichiers, et en particulier à cause de l'ioctl FIEMAP manquant, mais je ne sais pas ce qui cause ce comportement? Peux tu me dire?
ext4
tmpfs
sparse-files
l'humanité et la paix
la source
la source
Réponses:
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 .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 chargeFALLOC_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
:fallocate
fonctionne au niveau du fichier et lorsque vous exécutezmd5sum
sur un périphérique de bloc (demandant des lectures séquentielles), vous trébuchez sur l'écart exact entre la façon dont lefallocate()
syscall doit fonctionner. Nous pouvons le voir en action:En action, en utilisant votre exemple, nous voyons ce qui suit:
Maintenant ... cela répond à votre question de base. Ma devise générale est "devenir bizarre" alors j'ai creusé plus loin ...
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_PUNCHfallocate
et les périphériques de bloc se croisent.la source
tmpfs
prend en charge les fichiers clairsemés et punch_hole. C'est ce qui le rend si déroutant -tmpfs
prend en charge cela, alors pourquoi aller remplir les trous clairsemés lors de la lecture à travers un périphérique en boucle?losetup
ne change pas la taille du fichier, mais il crée un périphérique de bloc, qui sur la plupart des systèmes est ensuite analysé pour le contenu comme: y a-t-il une table de partition? existe-t-il un système de fichiers avec UUID? dois-je alors créer un / dev / disk / by-uuid / symlink? Et ces lectures provoquent déjà l'allocation de parties du fichier clairsemé, car pour une raison mystérieuse , tmpfs remplit des trous sur (certaines) lectures.loop.c
) et j'ai vu qu'il y avait deux fonctions pertinentes :lo_read_simple
&lo_read_transfer
. Il y a quelques différences mineures dans la façon dont ils font l'allocation de mémoire de bas niveau ...lo_read_transfer
demande en fait io non bloquant àslab.h
(GFP_NOIO
) lors d'unalloc_page()
appel.lo_read_simple()
d'autre part ne fonctionne pasalloc_page()
.