En mi ext4
partición del sistema de archivos puedo ejecutar el siguiente código:
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
cuyos rendimientos
Before:
0 sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
0 sparse100M
Haciendo lo mismo en tmpfs que con:
fs="/tmp"
rendimientos
Before:
0 /tmp/sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
102400 /tmp/sparse100M
lo que básicamente significa que algo que esperaba leer simplemente los datos, hizo que el archivo disperso "explotara como un globo".
Supongo que se debe a un soporte menos perfecto para archivos dispersos en el tmpfs
sistema de archivos, y en particular debido a la falta de FIEMAP ioctl, pero no estoy seguro de qué causa este comportamiento. ¿Usted pude decirme?
ext4
tmpfs
sparse-files
humanidad y paz
fuente
fuente
Respuestas:
En primer lugar, no estás solo en el enigma sobre este tipo de problemas.
Esto no solo se limita,
tmpfs
sino que ha sido una preocupación citada con NFSv4 .Cuando
md5sum
intenta escanear un archivo, elige explícitamente hacerlo en orden secuencial , lo que tiene mucho sentido en función de lo que md5sum intenta hacer.Como existen fundamentalmente "agujeros" en el archivo, esta lectura secuencial va a (en algunas situaciones) causar una copia en la operación de escritura para completar el archivo. Esto luego entra en un problema más profundo sobre si es
fallocate()
compatible o no con la implementación del sistema de archivosFALLOC_FL_PUNCH_HOLE
.Afortunadamente, no solo es
tmpfs
compatible con esto, sino que hay un mecanismo para "cavar" los agujeros de nuevo.Usando la utilidad CLI
fallocate
podemos detectar con éxito y volver a excavar estos agujeros.Según
man 1 fallocate
:fallocate
Sin embargo, opera en el nivel de archivo y cuando se está ejecutandomd5sum
contra un dispositivo de bloque (solicitando lecturas secuenciales) está tropezando con la brecha exacta entre cómofallocate()
debería funcionar la llamada al sistema. Podemos ver esto en acción:En acción, usando su ejemplo, vemos lo siguiente:
Ahora ... eso responde a tu pregunta básica. Mi lema general es "ponte raro", así que profundicé más ...
Verá que el simple hecho de realizar los
losetup
cambios cambia el tamaño del archivo disperso. Por lo tanto, esto se convierte en una combinación interesante de dóndetmpfs
, el mecanismo HOLE_PUNCHfallocate
y los dispositivos de bloque se cruzan.fuente
tmpfs
admite archivos dispersos y punch_hole. Eso es lo que lo hace tan confuso: esto estmpfs
compatible , así que ¿por qué ir y llenar los agujeros escasos al leer a través de un dispositivo de bucle?losetup
no cambia el tamaño del archivo, pero crea un dispositivo de bloque, que en la mayoría de los sistemas se escanea en busca de contenido como: ¿hay una tabla de partición? ¿Hay un sistema de archivos con UUID? ¿Debería crear un / dev / disk / by-uuid / symlink entonces? Y esas lecturas ya hacen que se asignen partes del archivo disperso, porque por alguna razón misteriosa , tmpfs llena agujeros en (algunas) lecturas.loop.c
) y vi que hay dos funciones relevantes :lo_read_simple
&lo_read_transfer
. Hay algunas diferencias menores en la forma en que realizan la asignación de memoria de bajo nivel ... enlo_read_transfer
realidad está solicitando io sin bloqueo desdeslab.h
(GFP_NOIO
) mientras realiza unaalloc_page()
llamada.lo_read_simple()
por otro lado no está realizandoalloc_page()
.