Precisa de sync ao escrever diretamente em dispositivos de bloco?

É comum, em tutoriais sobre como escrever imagens ISOHybrid em pendrives, a recomendação:

# dd if=xxx.iso of=/dev/sdx bs=1M status=progress
# sync

(bs= variando dependendo do gosto do freguês)

Esse sync após o dd, apesar de muito difundido, acredito não ter efeito. O manual da chamada de sistema sync() diz claramente que aplica-se apenas a sistemas de arquivos. O dispositivo de bloco bruto não é um sistema de arquivos. Portanto, o que faz efeito é adicionar a opção conv=fsync ao dd: quando a escrita termina no destino, chama fsync() no descritor de arquivo associado ao dispositivo, que o kernel traduz num comando adequado para os dados atingirem a mídia, como ATA_CMD_FLUSH, SYNCHRONIZE_CACHE, etc.

Observando o comportamento do kernel através do strace, estou convicto que, quando o dd chama close() no descritor de arquivo do dispositivo, o kernel automaticamente garante que os dados chegaram na mídia quando a função retorna, não sendo necessário usar conv=fsync; mal não faz, contudo.

O dd tentará truncar o arquivo de destino, via open(…, …|O_TRUNC) ou, caso seek= esteja presente, ftruncate(). O kernel ignora essa requisição nos dispositivos de bloco. Por boa prática, adicionamos notrunc. Cuide que, ao usar arquivos regulares como destino, a truncagem quase sempre é requerida.

Então, apenas dd conv=fsync,notrunc … basta.

Comentários