Você está correto sobre a localização do WARN, este código é da tag do kernel upstream v2.6.38
:
net/ipv4/tcp_input.c
2953 static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
2954 {
...
2964 if (WARN_ON(!tp->sacked_out && tp->fackets_out))
2965 tp->fackets_out = 0;
2966
Isso é discutido aqui e corrigido com commit:
commit 5b35e1e6e9ca651e6b291c96d1106043c9af314a
Author: Neal Cardwell <[email protected]>
Date: Sat Jan 28 17:29:46 2012 +0000
tcp: fix tcp_trim_head() to adjust segment count with skb MSS
A data coloca sua correção no kernel 3.3. Esta correção não foi backportada para a fonte EL5 da Red Hat (eu verifiquei o kernel 5.11 2.6.18-398) então se o seu NAS é baseado no CentOS 5 então isso não é fixo.
Vale a pena notar que nunca houve um 2.6.38
liberado para o EL5, então este não é um kernel Red Hat ou CentOS. Eu suponho que seu fornecedor NAS tenha um kernel upstream posterior, talvez tenha aplicado alguns patches e fornecido esse kernel na imagem de firmware de sua SAN.
Se você quiser corrigir isso, provavelmente precisará obter a origem do kernel 3.3 ou posterior, aplicar os patches de seu fornecedor de SAN e construir seu próprio kernel. Provavelmente vale a pena verificar se isso está corrigido no kernel do ltRe-lt que é 3.2.63-1.el5
, é muito perto de 3.3. Caso contrário, você poderia usar o arquivo .config
do ELRepo e make oldconfig
na nova fonte do kernel para responder a um mínimo de perguntas.
Dito isto, o grande não é um grande negócio de qualquer maneira. O WARN
ocorre devido a um erro de contabilidade no TCP. Se eu entendi o patch corretamente, as funções que consideram os dados transmitidos usando o TCP Segmentation Offloading fazem algumas suposições incorretas, resultando em um número de lixo de segmentos sendo contados sob algumas condições. O WARN
corrige isso retornando uma das contagens do segmento para 0. Eu acho que o pior que pode acontecer é que um pouco mais de dados do que o necessário seja retransmitido quando houver perda de pacotes.
Você pode conseguir contornar isso desabilitando o TSO. Verifique se você está usando o TSO com:
ethtool -g ethX
Se sim, desative-o com:
ethtool -G ethX tso off
Se isso funcionar, e sua rede for controlada pelos scripts internos do CentOS ( /etc/init.d/network
e amigos), então você pode escrever /sbin/ifup-local
para que a mudança se aplique toda vez que a interface for iniciada, assim:
#!/bin/bash
if [ $1 == "ethX" ]]; then
/sbin/ethtool -G $1 tso off
fi
Substitua ethX
pelo nome da sua interface de rede.