Na minha ext4
partição do sistema de arquivos, posso executar o seguinte 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
que produz
Before:
0 sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
0 sparse100M
Fazendo a mesma coisa no tmpfs como em:
fs="/tmp"
rendimentos
Before:
0 /tmp/sparse100M
2f282b84e7e608d5852449ed940bfc51 /dev/loop0
After:
102400 /tmp/sparse100M
o que basicamente significa que algo que eu esperava apenas ler os dados fez com que o arquivo esparso "explodisse como um balão"?
Espero que seja por causa do suporte menos perfeito para arquivos esparsos no tmpfs
sistema de arquivos e, em particular, devido à falta do FIEMAP ioctl, mas não sei ao certo o que causa esse comportamento? Você pode me dizer?
ext4
tmpfs
sparse-files
humanandpeace
fonte
fonte
Respostas:
Primeiro, você não está sozinho em intrigas sobre esse tipo de problema.
Isso não se limita apenas a,
tmpfs
mas tem sido uma preocupação citada com o NFSv4 .Quando
md5sum
está tentando digitalizar um arquivo, ele decide explicitamente fazer isso em ordem seqüencial , o que faz muito sentido com base no que o md5sum está tentando fazer.Como existem fundamentalmente "brechas" no arquivo, essa leitura seqüencial (em algumas situações) causa uma operação de cópia em gravação para preencher o arquivo. Isso então entra em uma questão mais profunda sobre a
fallocate()
implementação ou não do suporte ao sistema de arquivosFALLOC_FL_PUNCH_HOLE
.Felizmente, não apenas
tmpfs
suporta isso, mas também existe um mecanismo para "cavar" os buracos.Usando o utilitário CLI
fallocate
, podemos detectar e refazer esses furos com êxito.Conforme
man 1 fallocate
:fallocate
opera no nível do arquivo e, quando você está executandomd5sum
em um dispositivo de bloco (solicitando leituras seqüenciais), está observando o espaço exato entre como ofallocate()
syscall deve operar. Podemos ver isso em ação:Em ação, usando o seu exemplo, vemos o seguinte:
Agora ... isso responde à sua pergunta básica. Meu lema geral é "ficar estranho", então eu cavei mais ...
Você vê que apenas o ato de executar as
losetup
alterações altera o tamanho do arquivo esparso. Portanto, isso se torna uma combinação interessante de ondetmpfs
, o mecanismo HOLE_PUNCHfallocate
e os dispositivos de bloco se cruzam.fonte
tmpfs
suporta arquivos esparsos e punch_hole. Isso é o que a torna tão confusa -tmpfs
suporta isso, então por que preencher os buracos esparsos ao ler um dispositivo de loop?losetup
não altera o tamanho do arquivo, mas cria um dispositivo de bloco, que na maioria dos sistemas é verificado em busca de conteúdo como: existe uma tabela de partição? existe um sistema de arquivos com UUID? devo criar um / dev / disk / by-uuid / symlink então? E essas leituras já fazem com que partes do arquivo esparso sejam alocadas, porque, por algum motivo misterioso , o tmpfs preenche lacunas (algumas) leituras.loop.c
) e vi que há duas funções relevantes :lo_read_simple
&lo_read_transfer
. Existem algumas pequenas diferenças em como eles fazem a alocação de memória de baixo nível ...lo_read_transfer
na verdade, está solicitando io non-blocking deslab.h
(GFP_NOIO
) durante a realização de umaalloc_page()
chamada.lo_read_simple()
por outro lado, não está funcionandoalloc_page()
.