Laboratorio: rompe un driver
En este laboratorio vas a tumbar, a propósito, drivers de un sistema Ixolo en marcha, y a comprobar que el sistema se da cuenta y se repara mientras tus programas siguen funcionando. Después buscarás los límites: un servicio que no se reinicia y un servidor cuya caída detiene la máquina.
Lee antes Aislamiento y autorreparación, o tenlo abierto al lado. Calcula una hora.
0. Preparación
Sección titulada «0. Preparación»Arranca la ISO live en QEMU como en la guía rápida, con BIOS (no UEFI) y el tipo de máquina por defecto. Así tendrás una tarjeta de red Intel e1000 y un lector de CD IDE, que son los drivers que usa este laboratorio:
qemu-system-x86_64 -enable-kvm -cpu host -m 2G -smp 2 -cdrom ixolo-[VERSION]-amd64.isoEntra como root. Te vendrán bien dos terminales: la consola tiene cuatro,
cambias entre ellas con Alt+F1 a Alt+F4 (o Alt+Izquierda y
Alt+Derecha). Si la ventana de QEMU se queda esas teclas, lanza las órdenes
largas en segundo plano con &.
Opcional: haz que RS hable. Por defecto, el Reincarnation Server reinicia
los servicios en silencio. Si añades rs_verbose=1 a la línea de órdenes del
núcleo (elige Edit menu option en el menú de arranque), RS imprime una línea
que empieza por RS: en cada paso de un reinicio. El parámetro se lee en
rs/main.c; no lo hemos
probado en la ISO live.
1. Encuentra el driver
Sección titulada «1. Encuentra el driver»Cada servicio del sistema tiene una etiqueta y una entrada en
/proc/service:
ls /proc/serviceBusca e1000_0 (la primera tarjeta e1000) y tu driver de disco, que en la
máquina QEMU por defecto es at_wini_0. Lee la entrada del driver de red:
cat /proc/service/e1000_0filename: e1000endpoint: 72pid: 46restarts: 0flags: A--------policies: resetASRcount: 0Algo parecido a eso: los números serán otros. Apunta los valores de
endpoint, pid y restarts. La política reset significa «los reinicios
se notan y el endpoint cambia». El driver también es un proceso normal:
ps -ax | grep e1000Preguntas para tus notas: ¿qué PID y qué padre tiene? Busca
/etc/system.conf.d/e1000: ¿qué llamadas al núcleo puede hacer este driver?
2. Pon tráfico en marcha
Sección titulada «2. Pon tráfico en marcha»Comprueba que la interfaz de red (em0, el nombre que le da el driver e1000)
tiene dirección. La red integrada de QEMU reparte 10.0.2.15:
ifconfig em0Si no aparece una línea inet, pide una dirección por DHCP:
dhcpcd em0En la segunda consola (Alt+F2, vuelve a entrar como root), lanza un ping a la pasarela de QEMU y déjalo corriendo:
ping 10.0.2.2Cada línea de respuesta lleva un número icmp_seq. Un salto en esos números
indica paquetes perdidos.
Para una prueba mejor, mantén también una transferencia TCP. En el anfitrión, sirve un fichero grande:
dd if=/dev/urandom of=big.bin bs=1M count=500python3 -m http.server 8000y descárgalo en el invitado, tirando los datos:
ftp -o /dev/null http://10.0.2.2:8000/big.bin3. Mata el driver de red
Sección titulada «3. Mata el driver de red»De vuelta en la primera consola, mata el driver con el PID que encontraste:
kill -9 46Eres root, así que está permitido: PM pasa el SIGKILL al núcleo, que se lo
entrega a RS, el gestor de señales del driver. RS ve que el driver ha muerto y
arranca una copia nueva enseguida. Compruébalo:
cat /proc/service/e1000_0ps -ax | grep e1000Deberías ver un pid nuevo, un endpoint nuevo y restarts: 1. Salvo que
activaras rs_verbose, RS no imprime nada.
Mira ahora el ping y la descarga. Espera un pequeño salto en icmp_seq y un
breve parón en la transferencia mientras TCP retransmite; después, los dos
siguen. La pila de red (lwip) se enteró del driver nuevo por DS, el almacén
de datos, y volvió a configurar la tarjeta.
4. Túmbalo desde dentro
Sección titulada «4. Túmbalo desde dentro»kill -9 para el driver desde fuera. Para que falle como lo haría un driver
con un error, pide a RS que le inyecte una caída. El driver llama entonces él
mismo a panic():
minix-service fi e1000_0Esta vez la consola muestra las últimas palabras del driver, algo parecido a:
e1000(72): panic: Crash!syslib:panic.c: stacktrace: 0x... 0x... 0x...(el formato está en
libsys/panic.c).
Vuelve a mirar /proc/service/e1000_0: restarts ha subido.
Repítelo cuatro o cinco veces seguidas y mide cuánto tarda el driver en
volver. RS espera más tras cada fallo (2, 4, 8, 16 segundos, como mucho 30)
para que un driver que falla en cada arranque no pueda tener ocupada la
máquina. Mientras espera, puede que la entrada no aparezca en /proc/service.
5. Un driver de disco
Sección titulada «5. Un driver de disco»Ahora, el driver que hay debajo del sistema de ficheros raíz. En la ISO live
la raíz es el propio CD, leído a través de isofs y del driver at_wini_0
(ahci_0 en una máquina q35). /tmp, /var y /root son discos RAM que
sirve memory; no mates memory, es un servicio esencial.
cat /proc/service/at_wini_0kill -9 <su pid>ls -lR /usr/share > /dev/null && echo sigo leyendoLos drivers de disco se arrancan con una copia en memoria de su binario
(minix-service -c), así que RS puede reiniciarlos sin leer el disco que
controlan. La capa de bloques del sistema de ficheros ve fallar la petición
con el driver viejo, espera al endpoint nuevo y la repite. El ls debería
terminar, quizá tras una pausa.
6. Cuando el sistema no se repara
Sección titulada «6. Cuando el sistema no se repara»Un servicio al que se le dice que se quede parado. minix-service down
para un servicio a propósito, y RS no lo reinicia:
minix-service down e1000_0ls /proc/service | grep e1000ifconfig -aEl ping deja de recibir respuestas, y el resto del sistema sigue
funcionando. Recupera el driver con la misma orden que usa /usr/etc/rc al
arrancar, y vuelve a lanzar dhcpcd em0 si se ha perdido la dirección:
minix-service up /service/e1000 -label e1000_0 -args instance=0 -period 5HZLo mismo pasa con los servicios arrancados con minix-service run, que usa
el script de recuperación /etc/rs.single para parar el servicio en lugar de
reiniciarlo.
Un servidor esencial. Haz esto lo último: se espera que detenga la
máquina. Busca el PID de vfs con ps -ax y mátalo:
kill -9 <pid de vfs>RS arranca la copia de reserva de VFS, pero VFS pide un reinicio con
estado, y libsys lo rechaza porque la caída no fue controlada. Según el
código, deberías ver algo parecido a:
SEF(1): crash was not controlled, aborting transparent restartcore system service died: ...y después el sistema se detiene. VFS guarda todos los ficheros abiertos de todos los procesos; una copia nueva no conocería ninguno.
Preguntas
Sección titulada «Preguntas»- Tras el paso 3, el driver tenía un endpoint nuevo. ¿Por qué no puede la pila de red seguir usando el viejo? ¿Qué fallaría si los endpoints fueran simples números de ranura? (Consulta Paso de mensajes.)
- ¿Por qué TCP sobrevivió a la caída del driver, mientras que una caída de
la propia
lwip(lee/etc/rs.lwip) pierde todas las conexiones abiertas? - En un núcleo monolítico, ¿qué pasaría probablemente si el driver de red desreferenciara un puntero incorrecto? ¿Qué lo ha impedido aquí?
- ¿Por qué se arrancan los drivers de disco con
-c? ¿Qué pasaría sin esa opción, si el binario del driver está en el disco que controla? - ¿Por qué espera RS cada vez más tras cada caída? Pon un ejemplo de fallo en el que reiniciar al instante y para siempre sería perjudicial.
- Prueba
kill -9con los PID depmy devm. Leecheck_sig()ysig_proc()enminix/servers/pm/signal.c: ¿qué hace el código en cada caso, y por qué? - ¿Qué recuperación es transparente (los programas no lo notan) y cuál es solo visible pero superable? Usa tus notas de los pasos 3 a 6.
- La actualización en caliente sustituiría un driver por una versión nueva sin reiniciarlo. ¿Qué problema adicional tiene que resolver que un reinicio no tiene?
Para saber más
Sección titulada «Para saber más»- J. N. Herder et al., Failure Resilience for Device Drivers, DSN 2007: http://www.minix3.org/docs/jorrit-herder/dsn-dccs07.pdf
- La visión general de la fiabilidad de la wiki original (en inglés): https://wiki.minix3.org/doku.php?id=www:documentation:reliability
minix-service(8)y el código de RS enminix/servers/rs/.