Problema

En servidores que ejecutan Proxmox con ZFS como backend de almacenamiento, es frecuente encontrarse con un arranque que se detiene en un mensaje similar a:

PANIC: zfs: rt={spa=... vdev_guid=... ms_id=... ms_allocatable}: removing nonexistent segment from range tree (offset=... size=...)

El kernel entra en pánico antes de presentar el prompt de login, impidiendo cualquier acceso normal. El síntoma es idéntico independientemente de la distribución subyacente: el proceso de boot se interrumpe y la única vía de recuperación es iniciar en modo rescue o en un live CD. El pool ZFS aparece “online” cuando se inspecciona desde el entorno de rescate, pero el error persiste al intentar arrancar de nuevo.

Este tipo de panic no es exclusivo de una versión concreta de Proxmox; se trata de un patrón que ocurre cuando el motor de ZFS detecta inconsistencias internas en sus estructuras de rango (range tree) durante la inicialización del spa (storage pool allocator). Los administradores que gestionan varios pools, actualizan el kernel o cambian la configuración de vdevs pueden encontrarse con este comportamiento sin una pista clara en los logs tradicionales.

Causa

Las causas más habituales que desencadenan este panic son:

  1. Corrupción de metadatos del spa

    • Un apagado brusco, pérdida de energía o un reinicio forzado mientras ZFS estaba escribiendo datos puede dejar segmentos de rango huérfanos. El motor intenta liberar un segmento que ya no existe, lo que genera el mensaje de “removing nonexistent segment”.
  2. Desalineación o cambio de vdevs sin actualizar el GUID

    • Reemplazar discos, cambiar el orden de los dispositivos o mover pools entre hosts sin recrear los GUIDs puede provocar que ZFS interprete erróneamente la topología del pool. El vdev_guid que figura en el panic suele ser el del dispositivo que sufrió la alteración.
  3. Incompatibilidad entre versiones del kernel y del módulo ZFS

    • Algunas combinaciones de kernel y ZFS on Linux (ZoL) introducen cambios en la gestión de range trees. Si el kernel se actualiza pero el módulo ZFS no se recompila, el código que manipula los rangos puede fallar.
  4. Errores de hardware en la capa de bloques

    • Controladores SATA/PCIe defectuosos, cables sueltos o sectores malos en los discos pueden producir lecturas corruptas que, al ser interpretadas por ZFS, resultan en estructuras inconsistentes.
  5. Uso de zpool export/import con versiones diferentes

    • Exportar un pool con una versión de ZoL y volver a importarlo con otra que tenga cambios en la representación interna del spa también puede desencadenar el panic.

En la práctica, la mayoría de los casos se reducen a una combinación de corrupción de metadatos y desalineación de vdevs, sobre todo después de una actualización del kernel o de un cambio de hardware.

Solución

La estrategia consiste en aislar el pool, reparar sus metadatos y asegurar que el kernel y el módulo ZFS estén alineados. Los pasos siguientes son aplicables a cualquier instalación de Proxmox (o Debian/Ubuntu) que utilice ZFS.

1. Arrancar en modo rescue o live

Utiliza el menú de GRUB para seleccionar “Advanced options” → “Recovery mode” o arranca desde un USB live con soporte ZFS. El objetivo es obtener un entorno donde el kernel no intente montar automáticamente los pools.

2. Importar el pool de forma segura

zpool import -f -N -R /mnt zfspoolname
  • -f fuerza la importación aunque el pool parezca en uso.
  • -N evita el montaje automático, lo que permite inspeccionar sin activar los datasets.
  • -R /mnt define un punto de montaje temporal.

3. Verificar la integridad del pool

zpool status -v zfspoolname
zpool scrub -w zfspoolname

El scrub revisa cada bloque y corrige errores detectados. Si aparecen errores “cannot read” o “checksum errors”, anota los vdevs involucrados.

4. Reparar metadatos corruptos

ZFS incluye una herramienta interna para intentar reparar estructuras dañadas:

zpool clear -f zfspoolname
zpool upgrade -a

zpool clear -f elimina errores persistentes y upgrade -a asegura que todos los pools usen la última versión de metadatos compatible con el módulo actual.

Si el panic persiste después del scrub, se puede intentar un reimport con la opción -o readonly=on para montar en modo solo lectura y ejecutar:

zdb -e -p /mnt zfspoolname | grep "range tree"

zdb permite inspeccionar directamente los árboles de rango; buscar entradas duplicadas o huecos ayuda a confirmar la corrupción.

5. Reconstruir el módulo ZFS

En caso de sospecha de incompatibilidad entre kernel y módulo:

apt update
apt install --reinstall zfs-dkms
dkms autoinstall
update-initramfs -u -k all

Esto recompila el módulo ZoL contra el kernel actual y actualiza el initramfs, evitando que el panic se dispare antes de que el módulo se cargue.

6. Re‑exportar y volver a importar el pool

zpool export zfspoolname
zpool import -d /dev/disk/by-id zfspoolname

El uso de rutas by-id garantiza que los discos se identifiquen con su GUID permanente, evitando desalineaciones posteriores.

7. Reiniciar y validar

Reinicia el servidor de forma normal. Si el kernel arranca sin pánico, procede a montar los datasets y verifica su contenido.

Cuándo aplicar esta solución

  • Síntomas claros: kernel panic con mensaje “removing nonexistent segment from range tree” durante el boot.
  • Entorno: Proxmox, Debian o Ubuntu con ZFS como storage backend.
  • Situaciones típicas: después de una actualización del kernel, sustitución de discos, export/import de pools, o apagados inesperados.

No aplicar si el sistema arranca sin errores y solo muestra advertencias menores en zpool status. En ese caso, un simple zpool scrub suele ser suficiente.

Código

# 1. Importar sin montar
zpool import -f -N -R /mnt zfspoolname

# 2. Ejecutar scrub y esperar a que termine
zpool scrub -w zfspoolname

# 3. Limpiar errores y actualizar metadatos
zpool clear -f zfspoolname
zpool upgrade -a

# 4. Recompliar módulo ZFS
apt update
apt install --reinstall zfs-dkms
dkms autoinstall
update-initramfs -u -k all

# 5. Exportar e importar usando by-id
zpool export zfspoolname
zpool import -d /dev/disk/by-id zfspoolname

Verificación

  1. Comprobar que el kernel arranca

    • Observa el log de arranque (journalctl -b -0). No debe aparecer ninguna línea con PANIC: zfs.
  2. Validar estado del pool

    • zpool status -v zfspoolname debe mostrar state: ONLINE y scan: none requested.
    • No debe haber líneas errors: 0 con advertencias.
  3. Revisar integridad de los datasets

    • Monta los datasets y ejecuta zfs get all <dataset> para confirmar que los atributos críticos (compressratio, used, etc.) son consistentes.
  4. Monitorear durante 24‑48 h

    • Ejecuta zpool scrub -s para iniciar un scrub periódico y verifica que no reaparecen errores.

Notas adicionales

  • Snapshots como seguro: antes de cualquier cambio estructural (añadir vdevs, exportar pools) crea un snapshot del dataset raíz. Permite volver a un estado limpio si la reparación falla.
  • Hardware primero: si el panic reaparece después de la reparación, revisa cables SATA/PCIe y ejecuta smartctl -a /dev/sdX para detectar sectores defectuosos.
  • Evitar forzar imports: el uso excesivo de -f puede ocultar problemas subyacentes. Solo úsalo cuando estés seguro de que el pool no está activo en otro nodo.
  • Mantener versiones alineadas: establece una política de actualización que incluya tanto el kernel como el paquete zfs-dkms. La desincronía es una causa frecuente de panics inesperados.

Con estos pasos, la mayoría de los kernel panics originados por inconsistencias en los range trees de ZFS pueden ser diagnosticados y corregidos sin necesidad de reinstalar el host ni perder datos.