Construindo um sistema Embedded Linux tolerante a falhas baseado no módulo Mars ZX3 da Enclustra

Devido à carga de trabalho de especialistas, vários anos atrás, fomos forçados a dar um desenvolvimento às contrapartes. O desenvolvimento foi realizado no módulo Enclustra Mars ZX3, que usa o SOC ARM + FPGA Zynq-7020. Para construir o Linux, usamos o Bcl da Enclustra (bsp-xilinx), que foi ligeiramente modificado.

No processo de teste do software desenvolvido, encontramos imediatamente falhas de software quando a energia foi desligada. Durante a análise, verificou-se que os comandos de configuração enviados ao dispositivo pela rede foram gravados em arquivos que, quando ocorria uma falha de energia, às vezes eram vazios ou ausentes. Isso nos forçou a reconsiderar a ideologia de construir o assembly Linux que nos foi entregue. O processo de construção do sistema em si está bem descrito no site do fabricante do módulo, por isso não vou insistir nele. Descreverei apenas o que nos permitiu resolver a tarefa diante de nós, aumentando a confiabilidade e prevenindo falhas.

O módulo Mars ZX3 possui chips QSPI Flash e NAND Flash. No nosso caso, o módulo é carregado com o QSPI Flash, no qual o U-Boot foi gravado. Como os dois chips usam os mesmos pinos Zynq-7020, após o carregamento, o U-Boot alterna os pinos para o NAND Flash, em que seções de inicialização, Árvore de dispositivos, kernel Linux, sistema de arquivos ubifs e variáveis ​​de ambiente são gravadas em seções separadas. Além disso, todas as seções, exceto a seção com variáveis ​​de ambiente, foram reservadas (ou seja, havia duas seções). A seguir, um fragmento do arquivo Device Tree, que mostra como o NAND Flash foi quebrado na versão que nos foi transmitida pelos contratados:

partition@nand-linux { label = "nand-linux"; reg = <0x0 0x500000>; }; partition@nand-device-tree { label = "nand-device-tree"; reg = <0x500000 0x100000>; }; partition@nand-bootscript { label = "nand-bootscript"; reg = <0x600000 0x100000>; }; partition@nand-linux-second { label = "nand-linux-second"; reg = <0x700000 0x500000>; }; partition@nand-device-tree-second { label = "nand-device-tree"; reg = <0xC00000 0x100000>; }; partition@nand-bootscript-second { label = "nand-bootscript"; reg = <0xD00000 0x100000>; }; partition@nand-rootfs { label = "nand-rootfs"; reg = <0xE00000 0xF500000>; }; partition@nand-rootfs-second { label = "nand-rootfs"; reg = <0x10300000 0xF500000>; }; partition@boot-env { label = "nand-env"; reg = <0x1F800000 0x100000>; }; 

As segundas seções deveriam ser usadas quando as seções principais falharam. Para fazer isso, o Linux precisou implementar um processo que monitora a integridade do sistema e, no caso de uma falha, grava um valor na variável de ambiente que instrui a iniciar o sistema a partir das partições de backup. Este algoritmo deveria ser implementado no futuro.

Os dados de configuração foram registrados em duas pastas para backup, mas isso não salvou a situação. Supõe-se que, na ausência de arquivos de configuração, eles sejam criados novamente automaticamente, com as configurações padrão.

O problema é que o NAND Flash grava dados uma página de cada vez e a exclusão ocorre em blocos. Portanto, se ocorrer uma falha de energia durante a gravação dos dados, não apenas esses dados serão corrompidos, mas o sistema de arquivos poderá ser danificado. Iniciar um sistema de backup pode atrasar apenas a ocorrência de um problema. Embora neste caso seja possível realizar a restauração das principais partições a partir das de backup.

Decidimos seguir o outro caminho, montando o rootfs como um sistema de arquivos somente leitura e gravando arquivos de configuração para separar as seções de dados e backup que foram montadas para leitura e gravação. Nesse caso, a necessidade de partições de backup desaparece, mas as deixamos para o futuro, pois a quantidade de memória nos permitiu fazer isso. Se necessário, eles podem ser excluídos.

Como resultado, foi realizado o seguinte particionamento NAND Flash:

  partition@nand-linux { label = "nand-linux"; reg = <0x0 0x500000>; }; partition@nand-device-tree { label = "nand-device-tree"; reg = <0x500000 0x100000>; }; partition@nand-bootscript { label = "nand-bootscript"; reg = <0x600000 0x100000>; }; partition@nand-linux-second { label = "nand-linux-second"; reg = <0x700000 0x500000>; }; partition@nand-device-tree-second { label = "nand-device-tree"; reg = <0xC00000 0x100000>; }; partition@nand-bootscript-second { label = "nand-bootscript"; reg = <0xD00000 0x100000>; }; partition@nand-rootfs { label = "nand-rootfs"; reg = <0xE00000 0x9600000>; }; partition@nand-rootfs-second { label = "nand-rootfs"; reg = <0xA400000 0x9600000>; }; partition@nand-data { label = "nand-data"; reg = <0x13A00000 0x5F00000>; }; partition@nand-data-backup { label = "nand-data-backup"; reg = <0x19900000 0x5F00000>; }; partition@boot-env { label = "nand-env"; reg = <0x1F800000 0x100000>; }; 

Ao piscar NAND Flash usando o comando U-Boot, apagamos as seções nand-data e nand-data-backup :

 u-boot>nand erase.part nand-data u-boot>nand erase.part nand-data-backup 

No script de inicialização do Linux, implementamos a montagem do sistema de arquivos raiz como Somente Leitura, substituindo a linha no arquivo / etc / inittab no assembly Linux:

 ::sysinit:/bin/mount -o remount,rw / 

em

 ::sysinit:/bin/mount -o remount,ro / 

Adicionamos um script de inicialização à pasta /etc/init.d/ , que monta as seções nand-data e nand-data-backup para leitura e gravação. No caso de um erro de montagem (durante a primeira inicialização ou se o sistema de arquivos estiver danificado), essas partições são formatadas e remontadas. As pastas / mnt / data / e / mnt / backup / devem ser criadas anteriormente no sistema de arquivos raiz.

 #!/bin/sh # # datafs Mount datafs. # umask 077 start() { printf "Starting mount datafs..." /usr/sbin/ubiattach /dev/ubi_ctrl -m 8 /usr/sbin/ubiattach /dev/ubi_ctrl -m 9 mount_datafs_err=0; mount_datafs_backup_err=0; /bin/mount -t ubifs ubi1:datafs /mnt/data mount_datafs_err=$? if [ $mount_datafs_err -ne 0 ]; then /usr/sbin/ubidetach -p /dev/mtd8 /usr/sbin/ubiformat /dev/mtd8 -y /usr/sbin/ubiattach /dev/ubi_ctrl -m 8 /usr/sbin/ubimkvol /dev/ubi1 -N datafs -s 81MiB /bin/mount -t ubifs ubi1:datafs /mnt/data mount_datafs_err=$? fi /bin/mount -t ubifs ubi2:datafs /mnt/backup mount_datafs_backup_err=$? if [ $mount_datafs_backup_err -ne 0 ]; then /usr/sbin/ubidetach -p /dev/mtd9 /usr/sbin/ubiformat /dev/mtd9 -y /usr/sbin/ubiattach /dev/ubi_ctrl -m 9 /usr/sbin/ubimkvol /dev/ubi2 -N datafs -s 81MiB /bin/mount -t ubifs ubi2:datafs /mnt/backup mount_datafs_backup_err=$? fi printf "Mount datafs: " if [ $mount_datafs_err -ne 0 ]; then echo "Error" else echo "OK" fi printf "Mount backup datafs: " if [ $mount_datafs_backup_err -ne 0 ]; then echo "Error" else echo "OK" fi touch /var/lock/datafs } stop() { /bin/umount /mnt/data /bin/umount /mnt/backup rm -f /var/lock/datafs } restart() { stop sleep 1 start } case "$1" in start) start ;; stop) stop ;; restart|reload) restart ;; *) echo "Usage: $0 {start|stop|restart|reload}" exit 1 esac exit 0 

Ao fazer o download, se os arquivos de configuração na pasta / mnt / data / estiverem ausentes, eles serão baixados da pasta / mnt / backup / . Se não houver arquivos de configuração em / mnt / backup / , eles serão criados automaticamente a partir do software com parâmetros padrão. Se os arquivos estiverem presentes em / mnt / data / mas não em / mnt / backup / , eles serão copiados de / mnt / data / para / mnt / backup / . Todas essas operações são executadas pelo software do usuário.

No estágio seguinte, para aumentar a confiabilidade, recusamos gravar a configuração em um arquivo para cada comando. A configuração inteira agora está armazenada na RAM e, se necessário, por um comando separado pode ser salva em arquivos nas pastas / mnt / data / e / mnt / backup / .

Se, durante o trabalho, você precisar fazer alterações no sistema de arquivos raiz sem atualizar o dispositivo, poderá remontar o sistema no console para ler e escrever com o comando

 mount -o remount,rw / 

Faça as alterações e remonte novamente em Somente leitura:

 mount -o remount,ro / 

Source: https://habr.com/ru/post/pt483900/


All Articles