Skip to content

Deadlock de nfsd: causa raíz de los cuelgues del NAS (2026-07-26)

Nota (registro histórico): el NAS pasó de 192.168.0.237 a 192.168.0.20 en la renumeración IP cerrada el 2026-07-31, unos días después de este incidente. Las IPs .237 de las pilas de kernel capturadas abajo son las que eran ciertas en el momento del incidente — no se han tocado. Ver nas-reboot.md para el runbook vivo con la IP actual.

Investigación que cerró un problema abierto desde el 2026-07-14. Incluye las hipótesis falsas porque cada una costó tiempo y conviene no repetirlas.

La causa raíz

Deadlock del nfsd de Linux al destruir sesiones NFSv4. Capturado en vivo con pilas de kernel de ambos extremos:

NAS (servidor)
  nfsd                          wchan=__flush_workqueue
      __flush_workqueue  <-  nfsd4_destroy_session      (espera vaciar la cola de callbacks)
  kworker/u8:N+nfsd4_callbacks  wchan=rpc_shutdown_client
      rpc_shutdown_client <- nfsd4_process_cb_update <- nfsd4_run_cb_work   (trabajo EN esa cola)

208 (cliente)
  192.168.0.237-manager         wchan=rpc_wait_bit_killable
      rpc_call_sync <- nfs4_proc_destroy_session         (esperando al servidor)

Se esperan mutuamente. Cada episodio pierde un hilo nfsd para siempre (D-state, no se mata ni con kill -9). Se acumulan de uno en uno; cuando caen los 8, el NFS muere.

El estrés de E/S no cuelga el NAS directamente: hace que los clientes NFSv4 agoten su timeout, y es la reconexión la que dispara el bug. Por eso correlacionaba con el backup de PBS (06:40) y con el borrado de snapshots (03:00) sin que ninguno fuera la causa.

Kernel afectado: 6.1.120+ (TOS 6.0.794).

Corrección 2026-08-04: este runbook decía que TOS 7 traía el kernel 6.12 y que la actualización era por tanto un arreglo dirigido. Es falso, o al menos no verificado. TOS 7 se anunció en beta con 6.12, pero la página oficial del release final da un kernel en la rama 6.1.x (string mal formateado en el marketing de TerraMaster, no se pudo confirmar el punto exacto) — es decir, TerraMaster probablemente volvió atrás de 6.12 a un 6.1.x más probado antes del lanzamiento. No asumir que TOS 7 arregla esto sin confirmar el build de kernel exacto primero. Ver la sección de actualización más abajo para el objetivo real.

Cómo reconocerlo

Señal Valor
load1 clavado en un entero plano (1 por hilo perdido)
disco / red / nfsd req cero
procs_blocked 0 ← la clave
procs_running 1

procs_blocked cuenta sólo iowait; el load cuenta toda tarea en D. Si el load es 10 y los bloqueados 0, hay diez tareas en sueño ininterrumpible que no esperan disco: esperan un cerrojo. Histórico: 26-jul load=2 (2 hilos), 14-jul load=10 (8 hilos + 2).

Hipótesis falsas (y por qué cayeron)

Hipótesis Cómo se descartó
Backup de appdata satura el nfsd con 3 h de escritura Medido: escribía 18 GB en 20 min; las otras 3 h leía agujeros de un fichero sparse. Ver abajo.
gzip es el cuello del backup 42 MB/s → explicaría 11 min de 209
El NFS es lento 111 MB/s, satura la gigabit
Falta de RAM en el 208 PSI de memoria ≈1 %; el swap estaba rancio, no activo
Muchos ficheros pequeños 25 641 ficheros / 6,2 GB en 55 s
btrfs subvolume delete / snapshots / fichero CoW de 875 GB Amplifican el estrés, no son la causa
Un trabajo semanal los lunes a las 07:30 Artefacto del método: min_over_time[30m] recortaba el inicio real
Scrub de BTRFS El último fue el 16-may y quedó aborted

Lección de método: una ventana de agregación puede fabricar patrones inexistentes. Para fechar el inicio de un episodio, consultar a paso de 60 s.

Hallazgo colateral: backup de appdata, 3h29m → 18m33s

appdata ocupa 28 GB reales pero 2,1 TB aparentes: appdata/tunarr/data.ms/indexes/*/data.mdb es la LMDB de Meilisearch con max_map_size de 2 TiB y 287 MB asignados. du cuenta bloques; tar leía el tamaño aparente y se tragaba 2 TiB de ceros cada noche.

Cura: tar -S/--sparse (GNU tar ≥1.29 usa SEEK_HOLE). Sobre tunarr solo: 2,3 s frente a horas. Verificado que restaura el fichero con sus agujeros intactos (aparente=2199023255552 bloques_512=586928, idénticos).

Ante un backup absurdamente lento, el primer comando no es time al compresor:

du -sh DIR ; du -sh --apparent-size DIR     # si difieren mucho -> sparse

También se corrigió un livelock de la API .backup() de sqlite: reinicia la copia cada vez que un escritor toca la DB origen; con Music Assistant escribiendo no terminaba nunca (3h20m atascado, .snapshot a 0 bytes, sin llegar al tar). Cura: VACUUM INTO + timeout.

Automatización añadida

Qué Dónde Detalle
Captura forense NAS /usr/local/bin/nas-hang-forensics.sh + cron 1 min Tareas en D con pila de kernel; dmesg incremental. Escribe en /root (persiste); nunca toca /Volume1 para no colgarse con él.
Auto-reboot por deadlock NAS nas-volume-selfheal.sh ≥50 % hilos nfsd en D sostenido 10 minsysrq-b. 1-2 hilos = sólo registra.
Reconciliación 208 nfs-health-monitor.sh Foto de contenedores NFS vivos → congelada al primer fallo → restaurados al volver el NFS. Inerte en operación normal.
Replicación de logs 208 pull-nas-forensics.sh cron 10 min Copia el log del NAS al 208 con timeout.

Por qué el "sostenido 10 min" no es negociable

El 26-jul a las 19:41 los 8 hilos entraron en D a la vez por una tormenta de E/S y 6 se recuperaron en un minuto. Un disparo instantáneo habría reiniciado el NAS sin necesidad. Probado en simulacro con 6 casos, incluido ese.

Por qué la reconciliación no levanta "todo lo parado"

Sablier para contenedores a propósito (lazy-start), y trip-planner está en la lista de contenedores NFS. Un reconciliador ingenuo se pelearía con él cada 2 minutos.

Trampas de systemd encontradas

  1. OnUnitActiveSec en un watchdog es una bomba. Se ancla a la ejecución anterior: si el servicio se cuelga (justo cuando hace falta), no hay ancla y al morir el timer se apaga y no vuelve. Caso real: 19:41:54 arrancó sobre un NFS colgado, systemd lo mató a las 20:04:57, y quedó inactive 1 h 43 min → 19 contenedores caídos 2 horas. → Para vigilantes usar SIEMPRE OnCalendar + TimeoutStartSec.
  2. Un TimeoutStartSec corto mata recuperaciones legítimas. recover_nfs hace MAX_RETRIES=30 × 20 s = hasta 10 min válidos. Poner 90 s (error cometido y corregido) las abortaría. Valor actual: 900 s.

Actualización 2026-08-04: el vigilante se disparó de verdad, cascada a pmx-50, y mitigación NFSv3

Dos meses de convivencia con el bug (automatización de más arriba) fueron suficientes mientras los episodios eran raros y se autorrecuperaban. Dejaron de serlo: el NAS se reinició dos mañanas seguidas (node_boot_time_seconds en Prometheus, no inferido): 3-ago 07:50 y 4-ago 06:59, tras una semana entera estable (26-jul → 3-ago). El nas-volume-selfheal.sh (vigilante B) se disparó de verdad ambas veces, exactamente como estaba diseñado: nfsd crítico (≥50 % en D) sostenido >10 min → sysrq-b. Cierra el punto abierto de que "nunca se ha ejecutado de verdad".

Hallazgo nuevo: la cascada se lleva por delante a pmx-50

El 4-ago, mientras el NAS estaba en el deadlock (06:33–06:57), pmx-50 (el hipervisor físico) también se reinició en seco (06:44:49 → 06:45:35, arranque startall de VM208+PBS+ha-ml juntos). Su log de systemd se corta en seco a las 06:44:49 sin secuencia de apagado — nada de shutdown.target — justo después de 2+ minutos de pvestatd fallando en bucle contra el storage terramaster (unable to activate storage 'terramaster' - directory... unreachable). wdctl confirma que pmx-50 tiene un watchdog hardware SP5100 TCO armado con timeout de 10 segundos, alimentado por watchdog-mux de la HA de Proxmox (ha-manager statusfencing armed (CRM watchdog active)). La hipótesis mejor sostenida (no probada con una línea de log literal — un reset por watchdog no llega a volcar el log final) es auto-fencing de la HA de Proxmox: el atasco de E/S generalizado impidió que pve-ha-crm/lrm refrescaran el watchdog a tiempo. VM208 volvió a las 06:45 y arrancó contra un NAS que seguía colgado hasta las 06:59 — cascada plausible hacia el cuelgue de dockerd de 9h+ que reportó Vera ese mismo día.

El arreglo de fondo real: no es TOS 7, es Linux 6.1.129

Investigado en el tracker de Debian (bug #1071562), firma idéntica (nfsd4_destroy_session__flush_workqueue deadlock). Confirmado roto en 6.1.85–6.1.119, arreglado en 6.1.129 — dentro de la misma rama 6.1.x que ya corre TOS, sin necesitar el salto a TOS 7. TerraMaster ya ha movido este punto antes sin salto de versión mayor (TOS 6.0.650 subió 6.1.58→6.1.120). El objetivo real a vigilar en changelog de TOS 6.0.8xx+ es kernel ≥6.1.129, no "TOS 7".

No intentar sustituir el kernel a mano. TOS es un appliance con parches de vendor sobre BTRFS/RAID/hardware; un kernel fuera de su flujo de actualización firmado arriesga romper esa integración en una caja con el único RAID5 de casa detrás.

Due diligence sobre TOS 7 en el foro oficial (2026-08-04) — más riesgo del esperado

Leído el hilo oficial de release (forum.terra-master.com t=10183) y el de compatibilidad F4-423/NVMe (t=9591, buscar "kernel version load"). Tres hechos nuevos, dos buenos y uno que pesa más que el resto:

  • Paquete exacto: TOS 7.0.0747 (MD5 ba39bd4b7df89998d12af118beb3eba9) es el update real desde TOS 6.0.794 — no 7.0.0746, que es sólo para quien ya estaba en la beta. TM Support no publica el kernel exacto en las notas de este release (la página de support.terra-master.com con el changelog completo devolvió 500 al intentar leerla) — sigue sin confirmar si trae ≥6.1.129. No asumir nada sin volver a intentarlo antes de actualizar.
  • Bueno: el gotcha de BIOS/NVMe no aplica aquí. El F4-423 está en la lista de modelos que necesitan reordenar el boot de BIOS si el disco de sistema TOS vive en el M.2 NVMe. Verificado en vivo (lsblk + findmnt /): el / de este NAS está en md9, RAID1 sobre las tres HDD SATA (sda2/sdb2/sdc2) — el Crucial P310 NVMe es sólo la capa HyperCache (vg0-fc1_cpool), no el disco de sistema. El paso de BIOS del foro no aplica.
  • Malo: riesgo real y confirmado de romper permisos NFS/SMB, no sólo teórico. Las notas oficiales avisan de una "conversión de permisos" obligatoria post-update (400.000 carpetas ≈ 3h) y de que hay que reconfigurar shared folders creados por Snapshot. Un usuario real del foro (Schnorra, 20-jul-2026, mismo hilo del gotcha BIOS) confirma el problema en producción: "Upgraded to TOS7 no problem, BUT all my SMB/share permissions are borked and now all my media streaming libraries are broken" — TM Support responde que es el comportamiento esperado de la conversión y que hay que reconfigurar a mano. Este NAS depende de un export NFS con anonuid=1001,anongid=997 + ACLs manuales (setfacl -R -m u:1000:rwx) para salvar el mismatch uid 0↔1000 con media-208 — es exactamente el tipo de configuración "no estándar" con más probabilidad de no sobrevivir una conversión automática. Un TOS7 fallido en la conversión de permisos rompería el acceso de todos los clientes NFS a la vez, incluidos los 3 que ya se movieron a NFSv3 hoy.
  • Sin confirmar, pero avisado en notas oficiales: "After the update, the device IP address may change". Este NAS tiene IP estática .20 desde la renumeración del 2026-07-31, referenciada por IP literal en storage.cfg de pmx-50/51, el autofs de VM208, y los dos mounts de Supervisor de HA. Un cambio de IP durante el update rompería los cuatro a la vez. Verificar esto explícitamente (o fijarla de nuevo tras el update) antes de dar por buena cualquier futura actualización a TOS7.

Conclusión revisada: el caso para TOS 7 es más débil de lo que parecía el 4-ago por la mañana — no sólo el beneficio del kernel sigue sin confirmarse, sino que ahora hay un riesgo concreto y reportado de romper la configuración de permisos NFS que sostiene todo el media stack. Con la mitigación NFSv3 ya desplegada en 3/4 clientes sin tocar el NAS para nada, no hay prisa — esperar a que el kernel real de un TOS 6.0.8xx o TOS7 posterior se confirme ≥6.1.129 antes de considerar cualquier actualización mayor.

Mitigación desplegada: NFSv3 en 3 de 4 clientes

nfsd4_destroy_session no existe en NFSv3 (protocolo sin estado, sin sesiones ni canal de callback — son conceptos de NFSv4.1+). Cambiar de versión de protocolo evita la clase entera de bug sin esperar al parche de kernel. Confirmado servidor: rpcinfo -p en el NAS ya anunciaba v3 y v4 a la vez, sin tocar /etc/nfs.conf.

Pilotado con un mount de prueba en paralelo (lectura + escritura + limpieza, sin tocar producción) antes de aplicar en real. Desplegado 2026-08-04:

Cliente Mount Antes Después
pmx-50 / pmx-51 terramaster (storage.cfg, backend datastore PBS archive, 872 GB) v4.2, hard v3, hard (sin tocar)
VM 208 /mnt/nfs_media (autofs) v4.2, soft v3, soft
HA / VM 171 terramaster_media + terramaster_backup (Supervisor) v4.2, softerr CIFS vers=2.0 — ver abajo (protocolo distinto, no NFSv3)

Por qué terramaster (pmx) no pasó también a soft: ese mount tiene detrás pbs-archive.img, un loop-image ext4 de 872 GB que es el datastore archive de PBS (LXC 186, bind mount mp1: /mnt/pbs-archive). Un mount soft puede devolver error en una escritura a mitad si el NAS se cuelga — para un filesystem-en-un-fichero de backups reales, eso es peor que el hipervisor colgándose. Se dejó hard a propósito.

Procedimiento real usado en pmx-50 (LXC 186 tenía el bind mount activo, que ancla el NFS — no basta con systemctl stop mnt-pbs\x2darchive.mount):

pct shutdown 186 --timeout 30                     # libera el bind mount
systemctl stop "mnt-pbs\x2darchive.mount"          # desmonta el loop ext4
umount /mnt/pve/terramaster                        # ahora sí, limpio
pvesm set terramaster --options vers=3              # storage.cfg es cluster-wide
systemctl start "mnt-pve-terramaster.mount"         # remonta con v3
systemctl start "mnt-pbs\x2darchive.mount"          # reengancha el loop
pct start 186
pct exec 186 -- proxmox-backup-manager prune-job run archive-prune   # TASK OK, verificado

VM 208 (/etc/auto.nfs_media, -fstype=nfs4,...-fstype=nfs,vers=3,...): el autofs de este mount usa timeout=0 (no expira solo), así que el cambio exige desmontar a la fuerza + retrigger. Eso deja stale los bind mounts Docker de los 21 contenedores que montan /mnt/nfs_media (ver gotcha del 2026-07-16 más abajo en este mismo runbook set) — se resolvió con nfs-health-monitor.sh rebind, que ya existía para exactamente este caso. Verificado: jellyfin/sonarr/radarr/bazarr healthy, /data con el conteo de ficheros esperado.

HA (VM 171) inicialmente se quedó en v4.2 — límite de plataforma, no elección: el mount manager de Supervisor sólo expone --version para mounts CIFS (ha mounts update --help). Probado además contra la API cruda (PUT /mounts/terramaster_media con "version":"3"): responde 200 ok pero lo ignora en silencio — tras reload el mount seguía en v4.2.

Actualización (mismo día, más tarde): HA movida a SMB, no a NFSv3

En vez de forzar NFSv3 en un mount que Supervisor gestiona (que habría exigido salirse de su gestión, con riesgo de que lo revirtiera en el próximo reinicio/update — sistema que controla cosas físicas de casa, portero y calefacción), se cambió el protocolo entero: el NAS ya exporta [Media] y [backups] por Samba (mismos paths). nfsd4_destroy_session no existe en absoluto en Samba — es un daemon completamente distinto (smbd, no nfsd), así que esto no es una mitigación del bug, es quitarse del código que lo tiene.

smbpasswd -s -a monxas          # el usuario samba ya existía, sin password conocido
# Supervisor sólo acepta cifs vers "2.0" (no "3.0"/"3"/"3.1.1" — 400 de vuelta)
curl -X PUT .../mounts/terramaster_media -d '{"type":"cifs","share":"Media",...,"version":"2.0"}'
curl -X PUT .../mounts/terramaster_backup -d '{"type":"cifs","share":"backups",...,"version":"2.0"}'

Verificado: mount en HA muestra cifs vers=2.0, listado de /media/terramaster_media correcto. Con esto, los 4 clientes conocidos están fuera de NFSv4 (3 en NFSv3, 1 en CIFS) — el disparador del bug (reconexión de sesión NFSv4.1+) ya no puede venir de ningún tráfico propio de esta casa.

Intentado y descartado: subir el pool de hilos nfsd (8→32)

Con el trigger casi eliminado, esto era ya sólo colchón — pero se intentó de todas formas. No es posible sin parchear binarios propietarios. /etc/nfs.conf (threads=) y /etc/default/nfs-kernel-server (RPCNFSDCOUNT=) se sobrescriben en cada arranque del servicio: nfs-server.service ejecuta nfsdconf (symlink a un binario TOS allconf) que regenera /usr/share/nfs-kernel-server/conffiles/nfs-kernel-server.default con 8 hardcodeado — no hay campo para esto en /etc/tos/config/nfs.json ni en la UI. Mismo tipo de límite de plataforma que el de Supervisor de arriba. Revertido a estado original.

Añadido: alerta temprana antes del auto-reboot

Nueva métrica Prometheus nfsd_threads_dstate{host="tnas"} (collector /usr/local/bin/nfsd-dstate-collect.sh en el NAS, cron cada minuto, mismo patrón que smart-collect.sh) expone exactamente la señal que ya usaba nas-volume-selfheal.sh internamente, pero ahora visible fuera del NAS. Dos alertas nuevas en el grupo nas_health: nas_nfsd_dstate_degraded (warning, ≥1 hilo en D sostenido 2min) y nas_nfsd_dstate_critical (critical, ≥50% sostenido 3min — el vigilante reinicia solo a los 10min, así que esto llega antes del reboot automático, no lo sustituye). Validado con promtool check rules antes de desplegar. Objetivo: pasar de "sorpresa a las 7am" a "aviso con tiempo de reaccionar", aunque ahora mismo el disparador de esto ya no debería poder venir de ningún cliente propio.

Actualización 2026-08-05: NO era el mismo bug — nuevo culpable real, y agujero de alertas cerrado

La noche del 4→5 de agosto el NAS volvió a tocar 8/8 hilos nfsd en D varias veces (02:03→07:11+, dos veces 8/8 completo, llegó a 445/600s del auto-reboot a las 06:45). Con los 4 clientes ya fuera de NFSv4 desde el día anterior, la primera lectura obvia — "el bug volvió pese a todo" — era incorrecta. Dos hallazgos la desmienten:

  1. La firma del kernel es otra. Las pilas capturadas esa noche muestran nfsd bloqueado en btrfs_inode_lock, folio_wait_bit_common, balance_dirty_pages, btrfs_start_ordered_extentcero apariciones de nfsd4_destroy_session / rpc_shutdown_client en toda la ventana. Contención de locks de BTRFS bajo escritura pesada, no el deadlock de sesiones NFSv4.1+.
  2. Los hilos se recuperaban. El conteo de D subía y bajaba toda la noche (8→1→3→8→3…) en vez de solo subir — la firma de un deadlock permanente (como el de julio) es monotónica: nunca baja. Esto sí bajaba: contención transitoria, no pérdida de hilos.

Causa real, encontrada por Vera a las 07:13: el sync job de PBS main-to-archive (LXC 186, pull de main (ZFS local) a archive (NFS sobre el NAS), schedule: 04:30) se quedó escribiendo sin parar desde las 04:30, saturando NFS/BTRFS durante ~2.5h. Su propio log interno de PBS marcaba TASK ERROR: sync aborted a las 05:11, pero algo por debajo siguió escribiendo hasta que Vera lo paró a mano a las 07:13 (D-state 8→0, load 12→6, Recv-Q drenada). Historial del job: sus últimas ejecuciones registradas (11–16 de mayo) fallaban todas con unable to open chunk store at "/archive/.chunks" — el mismo problema de montaje inestable de siempre — y no hay entradas entre mayo y esta madrugada. Todo apunta a que anoche fue su primera ejecución real desde que el mount del archive se volvió fiable (arreglo del 2026-08-04), intentando sincronizar de golpe un main con datos de meses. Programación del sync job desactivada (sync-job update main-to-archive --delete schedule) hasta investigarlo con calma — no es un fix de una línea, y no hace falta que vuelva a dispararse sólo antes de mirarlo.

Agujero real: la alerta nueva de anoche no llegó a Telegram cuando más falta hacía

La política documentada del homelab es clara: GRAVE (riesgo de datos o caída total) → Telegram al instante vía un carril dedicado en Alertmanager + Vera en paralelo, sin depender de que las herramientas propias de Vera (message, PushNotification) funcionen — precisamente para que un fallo de esas herramientas no te deje a ciegas. La alerta nas_nfsd_dstate_critical que se añadió anoche (ver más arriba) nunca se registró en ese carril — ni en el matcher de alertmanager.yml ni en GRAVE_ALERTS de alert-bridge.py (LXC 100) — así que a las 06:46, cuando el NAS estaba a 445/600s del auto-reboot, sólo se intentó avisar por message (MCP desconectado) y PushNotification (Remote Control inactivo). Ninguno de los dos llegó. El aviso real no llegó hasta el digest de las 6h. Corregido: nas_nfsd_dstate_critical añadido a ambos matchers, validado con amtool check-config + amtool config routes test (resuelve a telegram-grave,vera), desplegado y recargado en ambos servicios.

Lección: cualquier alerta critical/GRAVE nueva tiene que registrarse en los DOS sitios (matcher de Alertmanager + GRAVE_ALERTS en el bridge) en el mismo cambio que la crea, no después. Ver el GOTCHA ya documentado en alertas_silencio_primero.md: "si divergen, Vera calla sobre algo que ya te avisó, o al revés" — se aplicó al revés esta vez (Vera SÍ lo intentó, pero por el canal equivocado).

Actualización 2026-08-05 (tarde): NOCOW rebuild del archive + fencing de pmx-50 confirmado y arreglado + sync job reactivado

Con la causa mecánica del btrfs_inode_lock de la sección anterior ya identificada (fragmentación CoW), esta tarde se atacó de raíz en vez de dejar el sync job apagado indefinidamente.

1. pbs-archive.img tenía 572.988 extents. El datastore archive de PBS es un ext4 dentro de un fichero sparse de 1.65TB sobre BTRFS (pbs-archive.img, montado por loop) — estructuralmente idéntico a una imagen de disco de VM, el patrón que peor lleva BTRFS reescrito in-place, y nunca se le puso chattr +C (NOCOW). Reconstruido con cp --sparse=always a un fichero nuevo con NOCOW desde el arranque, gobernador adaptativo (pausa el cp con SIGSTOP si el D-state del NAS llega a 3, reanuda tras 20s limpios) para no repetir el incidente mientras se reescriben ~996GB reales. Panel de seguimiento en vivo (index.html + status.json, servido por python3 -m http.server 8765 en el NAS) — detalle completo del proceso y las instrucciones en /root/nocow-rebuild/PLAN.md del NAS.

Verify de PBS tras el swap: 25/26 grupos limpios. El único fallo (vm/208/2026-08-04T01:22:28Z, manifest load error) no era corrupción del rebuild — el directorio sólo tenía .tmp sin finalizar, un snapshot a medio escribir de un intento anterior del sync job que la copia (byte-a-byte, preserva metadatos del ext4 interno) se limitó a heredar tal cual. Se borró (no era un snapshot válido, no hay pérdida real: el día antes y el día después están íntegros) y se liberó pbs-archive.img.pre-nocow-backup (~1TB) tras confirmar que el resto verificaba limpio.

2. Al reactivar el sync job sin rate-in para probar el arreglo, pmx-50 entero se cayó. No fue el NAS esta vez — el nfsd D-state se quedó en 0-2 todo el rato, nada que ver con el 8/8 de antes. El host físico completo (con las 8 VMs/LXCs que aloja, incluida la 208) tuvo un hard lockup y volvió por un reset, sin panic ni traza en pstore. Esto confirma, esta vez con línea de log literal, la hipótesis abierta desde el 4-ago: a las 22:18:10, en mitad de la sincronización del disco de la 208, el kernel de pmx-50 empezó a repetir nfs: server 192.168.0.20 not responding, still trying — y el log de ese arranque termina segundos después. El motivo: el storage terramaster de pmx-50 (/etc/pve/storage.cfg, usado también por la 51 vía config de cluster) sólo tenía vers=3montaje hard sin soft/timeo/retrans, a diferencia de los 4 clientes NFSv4→v3 ya endurecidos el 4-ago. Un hard mount bloquea indefinidamente ante cualquier hipo del servidor en vez de devolver error — con la transferencia a máxima velocidad fue suficiente para atascar el kernel entero.

Arreglo: pct stop 186systemctl stop mnt-pbs\x2darchive.mount (loop) → umount /mnt/pve/terramasterpvesm set terramaster --options vers=3,soft,timeo=150,retrans=3 → remount NFS → remount loop → pct start 186. (El guard timer pbs-archive-guard.timer re-monta el loop cada 5 min si lo ve caído — hay que pararlo mientras se hace esto a mano, si no compite con el unmount.) storage.cfg es de cluster, así que pmx-51 recoge las mismas opciones en su próximo remount — no se ha forzado ahí porque no aloja la 208 y no está implicado en esta caída, pero queda pendiente si algún día usa este storage con más intensidad.

Reintento tras el arreglo: limpio. TASK OK, pasó sin incidente por el mismo snapshot que tumbó el host la vez anterior (126.8 MiB/s), 25.57 GiB en 23.046 chunks a 82 MiB/s de media, sin D-state, sin caída. Sync job reactivado (schedule: 04:30, sin rate-in — no hizo falta limitarlo una vez arregladas las dos causas reales).

Qué queda abierto

  • Kernel ≥6.1.129 (o una versión de TOS que lo traiga) sigue siendo el único arreglo de fondo real en el servidor para el bug original de julio. Del lado cliente ya no queda ninguno de los 4 conocidos tocando NFSv4 — pero un quinto cliente futuro (o alguien montando a mano) sí podría.
  • El umbral del 50 % del vigilante sigue siendo un juicio, no un valor derivado de datos — aunque ahora sí sabemos que dispara correctamente en un incidente real, dos veces.
  • Las dos alertas nuevas de nfsd_threads_dstate no se han visto disparar en un incidente real — sólo verificado que cargan (promtool) y que el estado en reposo es correcto (inactive, valor 0).
  • La reconciliación de contenedores del 208 sigue sin verse en una avería real en la que de verdad hiciera falta (las dos de agosto se resolvieron con el reboot del NAS + rebind manual de este mismo trabajo, no con la reconciliación automática).
  • Prometheus retiene "30d o 5 GiB" y manda el tamaño: los datos del NAS sólo llegan a ~20 días.