Depurando um RCU Stall no Proxmox: A Causa Não Era a Placa de Rede
O servidor ficava inacessível de forma intermitente e precisava de reboot físico para voltar. Eu tinha acabado de trocar a placa de rede, então obviamente a culpa era da NIC.
Não era. Essa suposição me custou um dia.
A falsa correlação
A troca da placa e os crashes eram eventos independentes que por acaso ficaram próximos no tempo. Os logs eram inequívocos assim que eu de fato os li: a interface estava UP, sem erros, durante toda a janela do stall.
Essa é a armadilha que vale nomear. Quando duas coisas mudam por volta do mesmo momento, a mudança deliberada mais recente absorve toda a suspeita. É um prior razoável — e é exatamente por isso que você checa os logs antes de agir sobre ele.
O que estava realmente acontecendo
O pvestatd, daemon de estatísticas do Proxmox, estava dando segfault em Perl com general protection fault. Ao morrer, deixou um spinlock preso.
A cadeia a partir daí:
pvestatd[1193] segfault em Perl
→ sai com preempt_count=1 (spinlock nunca liberado)
→ BUG: scheduling while atomic: pvestatd/1193
→ "Fixing recursive fault but reboot is needed!"
→ RCU stalls a cada 3 minutos por ~42 horas
→ UI completamente inacessível
O RCU stall era o sintoma, não a causa. Quando um processo em contexto de kernel morre segurando um spinlock, o Read-Copy-Update não consegue avançar. O kernel detecta isso e reporta em alto e bom som — mas não se recupera sozinho.
Passei horas lendo sobre RCU stalls. O RCU era quem reclamava, não quem estava quebrado.
O agravante
O pvestatd.service vem com Restart=no.
Essa única linha transformou um crash recuperável em 42 horas de indisponibilidade. Com Restart=on-failure, o systemd teria reiniciado o daemon em dez segundos e o stall nunca teria persistido tempo suficiente para eu notar.
O daemon crashar esporadicamente é um bug conhecido e não resolvido — há vários relatos contra essa versão do Proxmox. Isso eu não consigo consertar. O que consigo consertar é como o sistema reage a isso.
Como diagnosticar esse padrão
O movimento-chave é ler o boot anterior, já que a evidência é destruída pelo reboot que restaura o serviço:
# 1. Listar boots anteriores
journalctl --list-boots
# 2. Inspecionar o boot antes do reboot
journalctl -b -1 -k | grep -E "BUG|segfault|general protection|panic" | head -20
# 3. Confirmar a ordem: o crash veio antes do primeiro RCU stall?
journalctl -b -1 -k | grep -E "rcu.*stall" | head -3
# 4. Identificar o processo
journalctl -b -1 -k | grep "segfault" | head -5
O passo três é a técnica inteira. Se o segfault aparece antes do primeiro stall, o processo que crashou é a sua causa raiz e o RCU é ruído. A causa precede o sintoma no log; você só precisa olhar mais cedo que a mensagem alarmante que chamou sua atenção.
O que eu mudei
A correção real foi um drop-in do systemd sobrescrevendo o default do upstream:
# /etc/systemd/system/pvestatd.service.d/restart.conf
[Service]
Restart=on-failure
RestartSec=10
Também instalei o kdump-tools com crashkernel=256M reservado, para que o próximo crash sério capture um vmcore em vez de me deixar inferir tudo a partir do journal.
A lição
A parte mais cara desse incidente não foi a indisponibilidade. Foram as horas investigando um componente que estava funcionando corretamente, porque confiei numa coincidência em vez dos logs.
Leia o boot anterior. Procure a primeira coisa que quebrou, não a coisa mais barulhenta que está reclamando.