From owner-freebsd-bugs@FreeBSD.ORG Thu Oct 21 17:50:20 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9F66B16A4CE for ; Thu, 21 Oct 2004 17:50:20 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 85E7F43D46 for ; Thu, 21 Oct 2004 17:50:20 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.11/8.12.11) with ESMTP id i9LHoKph077445 for ; Thu, 21 Oct 2004 17:50:20 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id i9LHoKkx077444; Thu, 21 Oct 2004 17:50:20 GMT (envelope-from gnats) Resent-Date: Thu, 21 Oct 2004 17:50:20 GMT Resent-Message-Id: <200410211750.i9LHoKkx077444@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, James Van Bokkelen Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1478B16A4CF for ; Thu, 21 Oct 2004 17:41:51 +0000 (GMT) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id AD16043D1D for ; Thu, 21 Oct 2004 17:41:50 +0000 (GMT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.12.11/8.12.11) with ESMTP id i9LHfoxq022429 for ; Thu, 21 Oct 2004 17:41:50 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.12.11/8.12.11/Submit) id i9LHfoYa022424; Thu, 21 Oct 2004 17:41:50 GMT (envelope-from nobody) Message-Id: <200410211741.i9LHfoYa022424@www.freebsd.org> Date: Thu, 21 Oct 2004 17:41:50 GMT From: James Van Bokkelen To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.3 Subject: kern/72970: em driver can hang when mbuf starvation occurs X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 Oct 2004 17:50:20 -0000 >Number: 72970 >Category: kern >Synopsis: em driver can hang when mbuf starvation occurs >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Oct 21 17:50:20 GMT 2004 >Closed-Date: >Last-Modified: >Originator: James Van Bokkelen >Release: 4.8 >Organization: Sandstorm Enterprises Inc. >Environment: FreeBSD ni8 4.8-RELEASE FreeBSD 4.8-RELEASE #0: Fri Oct 15 15:02:46 EDT 2004 prod@sandstorm.net:/usr/src/sys/compile/NI_3X_FREEBSD48_DUAL i386 >Description: In file sys/dev/em/if_em.c, in function process_receive_interrupts(), (at line 2469 in v1.2.2.16, still present in 1.50 viewed via CVS on 21-Oct-2004), there is a call to em_get_buf(). If this fails due to mbuf starvation, the driver presently counts the error, frees any chain being built, puts the old buffer back in the receive and breaks out of the while(current_desc->status...) loop. This results in the interrupt being dismissed without updating the receive queue tail pointer, and the card never interrupts again. >How-To-Repeat: Stress a FreeBSD system with an em interface by receiving a large amount of traffic in promiscuous mode from several different senders while simultaneously writing large amounts of data to the disk. Observe that the em interface stops receiving new packets, and starts rapidly counting missed packets. Condition can be cleared by ifconfig em0 down && ifconfig em0 up or ifconfig em0 media auto >Fix: I replaced the offending block of code with a goto: if (accept_frame) { if (em_get_buf(i, adapter, NULL) == ENOBUFS) { goto next_rx_pkt; /* treat starvation like a runt or overrun */ This is aimed at a new label in the 'else' clause of the enclosing 'if (accept_frame)': } else { next_rx_pkt: /* Come here when starvation forces us to re-use an mbuf cluster */ adapter->dropped_pkts++; em_get_buf(i, adapter, mp); if (adapter->fmp != NULL) m_freem(adapter->fmp); adapter->fmp = NULL; adapter->lmp = NULL; } /* Zero out the receive descriptors status */ This keeps the driver from prematurely dismissing the interrupt and going deaf to incoming packets. >Release-Note: >Audit-Trail: >Unformatted: