zfs enviar volume flutua misteriosamente

2

Por que a quantidade de dados em um fluxo de envio do zfs "flutua"? Eu esperaria que o envio de um instantâneo específico sempre produzisse exatamente os mesmos dados!

Os dados de teste abaixo foram criados por meio de algo como dd if=/dev/zero of=filename bs=1024 count=1000

Os instantâneos foram tirados em intervalos entre a criação dos arquivos de teste. Em seguida, enviei os dados repetidamente para / dev / null usando o comando-history para executar novamente o comando de novo e de novo rapidamente. Sem trapaça - os instantâneos foram tirados antes do teste e nenhuma quantidade de "gravação" no sistema de arquivos deve afetar o que acontece em um envio incremental, ou assim eu imagino.

sol10-primary:/TST> # ls -l
total 1007
-rw-r--r--   1 root     root      102400 Mar  4 12:01 data1
-rw-r--r--   1 root     root      102400 Mar  4 11:49 data2
-rw-r--r--   1 root     root          30 Mar  4 11:48 data3
-rw-r--r--   1 root     root      102400 Mar  4 11:50 data4
-rw-r--r--   1 root     root      102400 Mar  4 11:52 data5
-rw-r--r--   1 root     root      102400 Mar  4 11:53 data6
sol10-primary:/TST> # rm data5
sol10-primary:/TST> # dd if=/dev/zero of=data5 bs=1024 count=100          
100+0 records in
100+0 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
412+6 records in
412+6 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
412+5 records in
412+5 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
412+6 records in
412+6 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
402+32 records in
402+32 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
405+22 records in
405+22 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
412+6 records in
412+6 records out
sol10-primary:/TST> # zfs send -i s1 rpool/tst@s3 | dd bs=1024 > /dev/null
412+5 records in
412+5 records out
sol10-primary:/TST> # zfs list -o name,mountpoint,used,referenced,usedbychildren,usedbysnapshots -r rpool/tst
NAME          MOUNTPOINT   USED  REFER  USEDCHILD  USEDSNAP
rpool/tst     /TST         892K   532K          0      360K
rpool/tst@s1  -             20K   232K          -         -
rpool/tst@s2  -             20K   432K          -         -
rpool/tst@s3  -            120K   532K          -         -

Às vezes, no exemplo acima, criei um instantâneo e depois editei um arquivo existente, apenas para obter algo no valor "USEDBYSNAPSHOTS".

Esta é basicamente uma questão acadêmica, eu suspeito que a variação esteja dentro de um limite muito pequeno, só percebi aqui porque meus próprios dados de teste são muito pequenos.

    
por Johan 04.03.2013 / 11:41

1 resposta

2

Não use dd com pipes. dd é de baixo nível. É uma interface para as chamadas do sistema read e write .

Quando você faz um dd bs=1024 count=1 , ele faz um read(0, buf, 1024) .

Se read retornar menos dados que 1024 bytes (por exemplo, porque o canal contém apenas 200 bytes no momento), dd não tentará novamente o read para obter os 824 bytes ausentes, ele informará um erro bloco incompleto lido no final (a parte depois de + ). A mesma coisa pode acontecer ao escrever também.

É por isso que é perigoso usar dd em tubos, a menos que você possa garantir que os processos de gravação ou leitura no tubo o façam em proporções proporcionais ao tamanho do bloco e divisores para o tamanho do tubo. que você terá blocos completos.

(echo AAAA; sleep 1; echo BBBBBB) | dd bs=3 > /dev/null
3+2 records in
3+2 records out

Isso não é um problema muito grande aqui, pois estamos apenas escrevendo o que lemos, mas pode ser mais problemático quando, por exemplo, você especificar um count .

O GNU dd tem -iflag fullblock para contornar isso:

$ (echo AAAA; sleep 1; echo BBBBBB) | dd bs=3 iflag=fullblock > /dev/null
4+0 records in
4+0 records out
12 bytes (12 B) copied, 1.00068 s, 0.0 kB/s
    
por 04.03.2013 / 15:24

Tags