Temos placa personalizada baseada em beaglebone black com 256 MB de RAM e 4 GB eMMC. Placa roda kernel Linux 4.9
estamos nos deparando com uma situação em que criamos um arquivo tempfs
e depois da validação, temos que movê-lo para a partição ext4 do eMMC. Arquivo nada além de umcertificate
em algumas situações, temos vários certificados em um diretório, portanto, precisamos mover todo o diretório de tempfs para a partição ext4 no eMMC.
Portanto, um dos problemas que nos preocupa é a atomicity
operação mv
(movimento).
De acordo rename
com a chamada do sistema, a renomeação da página de manual do Linux é uma operação atômica.
http://man7.org/linux/man-pages/man2/rename.2.html
No entanto, não temos certeza se a operação de renomeação envolve mover arquivos entre dois sistemas de arquivos, a atomicidade ainda está disponível ou não. Então, a pergunta é: está movendo o arquivo de tmpfs
para ext4
o atômico?
Obviamente, uma solução possível é manter os arquivos em uma pasta diferente na mesma partição (no mesmo sistema de arquivos, obviamente) e renomeá-lo usando mv
. Para diretório usando a abordagem abaixo de renomeação
SRC_dir --> TMP_DEST_dir
DEST_dir --> BAK_DEST_dir
TMP_DEST_dir --> DEST_dir
delete BAK_DEST_dir
Alguma sugestão de alternativas?
EDIT
Depois de receber a resposta, tentei seguir o código de teste na placa,
#include <stdio.h>
#include <errno.h>
int main()
{
int retcode = 0;
system("touch /tmp/rename_test");
retcode = rename("/tmp/rename_test", "/home/fs_rename_test");
if ( retcode < 0) {
printf("errno : %d\n",errno );
perror("Error occurred while renaming file");
return 1;
}
return 0;
}
Que retornou após a saída. E confirmou que a renomeação não funciona no sistema de arquivos cruzado.
errno : 18
Error occurred while renaming file: Invalid cross-device link
Não. Renomeações como tal só funcionam dentro de um sistema de arquivos. A página de manual para
rename(2)
menciona explicitamente o erro que é retornado ao tentar renomear nos pontos de montagem:As movimentações entre sistemas de arquivos precisam ser feitas como uma combinação de uma cópia e uma exclusão.
mv
fará isso para você serename()
não funcionar, mas não será atômico nesse caso.A maneira simples de contornar isso seria primeiro copiar o arquivo para um local temporário no mesmo sistema de arquivos. Em geral, é mais simples colocar o arquivo temporário no mesmo diretório que o destino final, já que esse é o único local com garantia de estar no mesmo sistema de arquivos. Claro que isso requer que qualquer processo que esteja trabalhando nos arquivos tenha alguma lógica para ignorar o temporário baseado em seu nome.
Aproximadamente, algo assim deve funcionar para um arquivo:
Observe que o processo que você descreve para um diretório é essencialmente este:
O que não é ruim, mas não é atômico. Há um momento de tempo entre as duas execuções de
mv
(ou chamadas pararename()
), quando/dst/dir
não existe. Isso pode ser contornado acessando o diretório por meio de um link simbólico, já que o link pode ser substituído atomicamente por uma renomeação.