Debido a la carga de trabajo de especialistas, hace varios años nos vimos obligados a dar un desarrollo a las contrapartes. El desarrollo se llevó a cabo en el módulo Enclustra Mars ZX3, que utiliza el SOC ARM + FPGA Zynq-7020. Para construir Linux, utilizamos Bcl de Enclustra (bsp-xilinx), que fue ligeramente modificado.
En el proceso de probar el software desarrollado, inmediatamente encontramos fallas de software cuando se apagó la alimentación. Durante el análisis, se descubrió que los comandos de configuración enviados al dispositivo a través de la red se escribían en archivos que, cuando ocurría una falla de energía, a veces resultaba estar vacía o completamente ausente. Esto nos obligó a reconsiderar la ideología de construir el ensamblado de Linux que nos fue entregado. El proceso de construcción del sistema en sí está bien descrito en el
sitio del fabricante del módulo, por lo que no me detendré en él. Solo describiré lo que nos ha permitido resolver la tarea que tenemos ante nosotros de aumentar la confiabilidad y prevenir fallas.
El módulo Mars ZX3 tiene chips QSPI Flash y NAND Flash. En nuestro caso, el módulo se carga con QSPI Flash, en el que se escribió U-Boot. Dado que ambos chips usan los mismos pines Zynq-7020, después de cargar U-Boot cambia los pines a NAND Flash, en el que el script de arranque, el Árbol de dispositivos, el kernel de Linux, el sistema de archivos ubifs y las variables de entorno se escriben en secciones separadas. Además, todas las secciones, excepto la sección con variables de entorno, estaban reservadas (es decir, había dos de esas secciones). El siguiente es un fragmento del archivo del Árbol de dispositivos, que muestra cómo se rompió NAND Flash en la versión que nos transmitieron los contratistas:
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>; };
Se suponía que las segundas secciones se utilizarían cuando las secciones principales fallaran. Para hacer esto, Linux tuvo que implementar un proceso que monitorea la integridad del sistema y, en caso de falla, escribe un valor en la variable de entorno que le indica que inicie el sistema desde las particiones de respaldo. Se suponía que este algoritmo se implementaría en el futuro.
Los datos de configuración se registraron en dos carpetas para la copia de seguridad, pero esto no salvó la situación. Se supone que, en ausencia de archivos de configuración, se vuelven a crear automáticamente, con la configuración predeterminada.
El problema es que NAND Flash escribe datos una página a la vez y el borrado se produce en bloques. Por lo tanto, si se produce un fallo de alimentación durante la grabación de datos, no solo estos datos se dañarán, sino que el sistema de archivos puede dañarse. Iniciar un sistema de respaldo solo puede retrasar la aparición de un problema. Aunque en este caso es posible realizar la restauración de las particiones principales desde las de respaldo.
Decidimos ir hacia otro lado, montando rootfs como un sistema de archivos de solo lectura y escribiendo archivos de configuración para separar
las secciones de
datos y
copias de seguridad que se montaron para leer y escribir. En este caso, la necesidad de particiones de respaldo desaparece, pero las dejamos para el futuro, ya que la cantidad de memoria nos permitió hacer esto. Si es necesario, se pueden eliminar.
Como resultado, se realizó el siguiente particionamiento 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>; };
Al flashear NAND Flash con el comando U-Boot, borramos las secciones
nand-data y
nand-data-backup :
u-boot>nand erase.part nand-data u-boot>nand erase.part nand-data-backup
En el script de arranque de Linux, implementamos el montaje del sistema de archivos raíz como de solo lectura, reemplazando la línea en el archivo / etc / inittab en el ensamblado de Linux:
::sysinit:/bin/mount -o remount,rw /
en
::sysinit:/bin/mount -o remount,ro /
Agregamos un script de arranque a la carpeta
/etc/init.d/ , que monta las secciones
nand-data y
nand-data-backup para leer y escribir. En caso de un error de montaje (durante el primer arranque o si el sistema de archivos está dañado), estas particiones se formatean y se vuelven a montar. Las carpetas
/ mnt / data / y
/ mnt / backup / deben crearse previamente en el sistema de archivos raíz.
Al descargar, si faltan los archivos de configuración en la carpeta
/ mnt / data / , se descargan de la carpeta
/ mnt / backup / . Si no hay archivos de configuración en
/ mnt / backup / , se crean automáticamente desde el software con los parámetros predeterminados. Si los archivos están presentes en
/ mnt / data / pero no en
/ mnt / backup / , se copian de
/ mnt / data / a
/ mnt / backup / . Todas estas operaciones son realizadas por el software del usuario.
En la siguiente etapa, para aumentar la confiabilidad, nos negamos a escribir la configuración en un archivo para cada comando. Toda la configuración ahora se almacena en RAM y, si es necesario, mediante un comando separado se puede guardar en archivos en las carpetas
/ mnt / data / y
/ mnt / backup / .
Si durante el trabajo necesita realizar cambios en el sistema de archivos raíz sin actualizar el dispositivo, puede volver a montar el sistema desde la consola para leer y escribir con el comando
mount -o remount,rw /
Realice cambios y luego vuelva a montar en Solo lectura:
mount -o remount,ro /