Por padrão, o rsync compara arquivos por tamanho e registro de data e hora, mas um dispositivo não tem um tamanho, portanto, ele deve calcular as diferenças usando o algoritmo delta que é descrito neste relatório técnico . Vagamente, o arquivo remoto é dividido em blocos de um tamanho escolhido, e os checksums destes são enviados de volta. O arquivo local é similarmente verificado em blocos e comparado com a lista. O controle remoto é então informado sobre como reagrupar os blocos que ele tem para refazer o arquivo, e os dados para os blocos que não correspondem são enviados.
Você pode ver isso pedindo a saída de depuração no nível 3 apenas para o algoritmo deltasum com a opção --debug=deltasum3
. Você pode especificar um tamanho de bloco com -B
para simplificar os números. Por exemplo, para um arquivo que já foi copiado uma vez, uma segunda execução de
rsync -B 100000 --copy-devices -avv --debug=deltasum3 --no-W /dev/sdd /tmp/mysdd
produz uma saída como esta, mostrando a soma de verificação para cada bloco:
count=164 rem=84000 blength=100000 s2length=2 flength=16384000
chunk[0] offset=0 len=100000 sum1=61f6893e
chunk[1] offset=100000 len=100000 sum1=32f30ba3
chunk[2] offset=200000 len=100000 sum1=45b1f9e5
...
Você pode vê-lo correspondendo às somas de verificação do outro dispositivo de maneira bastante trivial, já que não há diferenças:
potential match at 0 i=0 sum=61f6893e
match at 0 last_match=0 j=0 len=100000 n=0
potential match at 100000 i=1 sum=32f30ba3
match at 100000 last_match=100000 j=1 len=100000 n=0
potential match at 200000 i=2 sum=45b1f9e5
match at 200000 last_match=200000 j=2 len=100000 n=0
...
No final, o campo data=
é 0, mostrando que nenhum dado novo foi enviado.
total: matches=164 hash_hits=164 false_alarms=0 data=0
Se agora corrompermos a cópia sobrescrevendo o meio do arquivo:
echo test | dd conv=block,notrunc seek=80 bs=100000 of=/tmp/mysdd
touch -r /dev/sdd /tmp/mysdd
então a depuração de rsync nos mostra uma nova soma de verificação para o bloco 80, mas não corresponde a ela. Vamos do jogo 79 para o 81:
chunk[80] offset=8000000 len=100000 sum1=a73cccfe
...
potential match at 7900000 i=79 sum=58eabec6
match at 7900000 last_match=7900000 j=79 len=100000 n=0
potential match at 8100000 i=81 sum=eba488ba
match at 8100000 last_match=8000000 j=81 len=100000 n=100000
No final, temos data=100000
mostrando que todo um novo bloco de dados teve que ser enviado.
total: matches=163 hash_hits=385 false_alarms=0 data=100000
O número de correspondências foi reduzido em 1, para a soma de verificação de bloco corrompido que não conseguiu corresponder. Talvez o hash tenha aumentado porque perdemos a correspondência sequencial.
Se procurarmos mais no mesmo relatório de tecnologia, alguns resultados do teste são exibidos e falso alarmes são descritos como "o número de vezes que a soma de verificação de rolamento de 32 bits correspondeu, mas a soma de verificação strong não". Cada bloco tem uma soma de verificação simples e uma soma de verificação md5 feita (md4 em versões mais antigas). A soma de verificação simples é fácil de procurar usando uma tabela de hash, pois é um inteiro de 32 bits. Depois de corresponder a uma entrada, a soma de verificação de 16 bytes md5 mais longa também é comparada e, se não corresponder, é um alarme falso e a pesquisa continua.
Meu exemplo usa um dispositivo de chave usb muito pequeno (e antigo) de 16Mbytes, e o tamanho mínimo da tabela de hash é 2 ** 16, ou seja, 65536 entradas, por isso fica bem vazio ao manter as 164 entradas de bloco que tenho. Tantos alarmes falsos são normais e mais uma indicação de eficiência do que qualquer outra coisa.