From nobody@FreeBSD.org  Mon Aug 31 10:06:01 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 59F881065672
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 31 Aug 2009 10:06:01 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 48B188FC21
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 31 Aug 2009 10:06:01 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n7VA61Et052388
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 31 Aug 2009 10:06:01 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n7VA61Ep052387;
	Mon, 31 Aug 2009 10:06:01 GMT
	(envelope-from nobody)
Message-Id: <200908311006.n7VA61Ep052387@www.freebsd.org>
Date: Mon, 31 Aug 2009 10:06:01 GMT
From: Patroklos Argyroudis <argp@census-labs.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Memory leak in output_listing() in file sys/dev/aic7xxx/aicasm/aicasm.c
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         138379
>Category:       kern
>Synopsis:       [aic7xxx] [patch] Memory leak in output_listing() in file sys/dev/aic7xxx/aicasm/aicasm.c
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    brueffer
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Aug 31 10:10:02 UTC 2009
>Closed-Date:    Sat Oct 31 12:03:38 CET 2009
>Last-Modified:  Tue May  7 08:00:00 UTC 2013
>Originator:     Patroklos Argyroudis
>Release:        8.0-CURRENT
>Organization:
census, inc
>Environment:
N/A
>Description:
There is a memory leak of pointer func_values which is allocated in line 554 but not freed.
>How-To-Repeat:
N/A
>Fix:
Patch attached.

Patch attached with submission follows:

--- ./sys/dev/aic7xxx/aicasm/aicasm.c.orig	2009-08-27 22:00:05.000000000 +0300
+++ ./sys/dev/aic7xxx/aicasm/aicasm.c	2009-08-27 22:48:58.000000000 +0300
@@ -643,6 +643,7 @@
 	while(fgets(buf, sizeof(buf), ifile) != NULL)
 		fprintf(listfile, "             %s", buf);
 
+	free(func_values);
 	fclose(ifile);
 }
 


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-scsi 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Aug 31 10:32:53 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=138379 
State-Changed-From-To: open->patched 
State-Changed-By: brueffer 
State-Changed-When: Wed Oct 21 16:09:21 CEST 2009 
State-Changed-Why:  
Leak plugged, thanks for the report! 


Responsible-Changed-From-To: freebsd-scsi->brueffer 
Responsible-Changed-By: brueffer 
Responsible-Changed-When: Wed Oct 21 16:09:21 CEST 2009 
Responsible-Changed-Why:  
MFC reminder. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=138379 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/138379: commit references a PR
Date: Wed, 21 Oct 2009 14:09:19 +0000 (UTC)

 Author: brueffer
 Date: Wed Oct 21 14:09:06 2009
 New Revision: 198327
 URL: http://svn.freebsd.org/changeset/base/198327
 
 Log:
   Add a missing free() call.
   
   PR:		138379
   Submitted by:	Patroklos Argyroudis <argp@census-labs.com>
   Reviewed by:	gibbs
   MFC after:	1 week
 
 Modified:
   head/sys/dev/aic7xxx/aicasm/aicasm.c
 
 Modified: head/sys/dev/aic7xxx/aicasm/aicasm.c
 ==============================================================================
 --- head/sys/dev/aic7xxx/aicasm/aicasm.c	Wed Oct 21 14:05:51 2009	(r198326)
 +++ head/sys/dev/aic7xxx/aicasm/aicasm.c	Wed Oct 21 14:09:06 2009	(r198327)
 @@ -639,6 +639,8 @@ output_listing(char *ifilename)
  		}
  		instrptr++;
  	}
 +	free(func_values);
 +
  	/* Dump the remainder of the file */
  	while(fgets(buf, sizeof(buf), ifile) != NULL)
  		fprintf(listfile, "             %s", buf);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: brueffer 
State-Changed-When: Sat Oct 31 12:03:23 CET 2009 
State-Changed-Why:  
MFCs done. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=138379 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/138379: commit references a PR
Date: Tue,  7 May 2013 07:52:26 +0000 (UTC)

 Author: adrian
 Date: Tue May  7 07:52:18 2013
 New Revision: 250326
 URL: http://svnweb.freebsd.org/changeset/base/250326
 
 Log:
   Re-work how transmit buffer limits are enforced - partly to fix the PR,
   but partly to just tidy up things.
   
   The problem here - there are too many TX buffers in the queue! By the
   time one needs to transmit an EAPOL frame (for this PR, it's the response
   to the group rekey notification from the AP) there are no ath_buf entries
   free and the EAPOL frame doesn't go out.
   
   Now, the problem!
   
   * Enforcing the TX buffer limitation _before_ we dequeue the frame?
     Bad idea. Because..
   * .. it means I can't check whether the mbuf has M_EAPOL set.
   
   The solution(s):
   
   * De-queue the frame first
   * Don't bother doing the TX buffer minimum free check until after
     we know whether it's an EAPOL frame or not.
   * If it's an EAPOL frame, allocate the buffer from the mgmt pool
     rather than the default pool.
   
   Whilst I'm here:
   
   * Add a tweak to limit how many buffers a single node can acquire.
   * Don't enforce that for EAPOL frames.
   * .. set that to default to 1/4 of the available buffers, or 32,
     whichever is more sane.
   
   This doesn't fix issues due to a sleeping node or a very poor performing
   node; but this doesn't make it worse.
   
   Tested:
   
   * AR5416 STA, TX'ing 100+ mbit UDP to an AP, but only 50mbit being received
     (thus the TX queue fills up.)
   * .. with CCMP / WPA2 encryption configured
   * .. and the group rekey time set to 10 seconds, just to elicit the
     behaviour very quickly.
   
   PR:		kern/138379
 
 Modified:
   head/sys/dev/ath/if_ath.c
   head/sys/dev/ath/if_ath_sysctl.c
   head/sys/dev/ath/if_athioctl.h
   head/sys/dev/ath/if_athvar.h
 
 Modified: head/sys/dev/ath/if_ath.c
 ==============================================================================
 --- head/sys/dev/ath/if_ath.c	Tue May  7 07:44:07 2013	(r250325)
 +++ head/sys/dev/ath/if_ath.c	Tue May  7 07:52:18 2013	(r250326)
 @@ -694,6 +694,13 @@ ath_attach(u_int16_t devid, struct ath_s
  	 */
  	sc->sc_txq_mcastq_maxdepth = ath_txbuf;
  
 +	/*
 +	 * Default the maximum queue depth for a given node
 +	 * to 1/4'th the TX buffers, or 64, whichever
 +	 * is larger.
 +	 */
 +	sc->sc_txq_node_maxdepth = MAX(64, ath_txbuf / 4);
 +
  	/* Enable CABQ by default */
  	sc->sc_cabq_enable = 1;
  
 @@ -2661,33 +2668,98 @@ ath_start(struct ifnet *ifp)
  	ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start: called");
  
  	for (;;) {
 -		ATH_TXBUF_LOCK(sc);
 -		if (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree) {
 -			/* XXX increment counter? */
 -			ATH_TXBUF_UNLOCK(sc);
 +		/*
 +		 * Grab the frame that we're going to try and transmit.
 +		 */
 +		IFQ_DEQUEUE(&ifp->if_snd, m);
 +		if (m == NULL)
 +			break;
 +		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
 +
 +		/*
 +		 * Enforce how deep a node queue can get.
 +		 *
 +		 * XXX it would be nicer if we kept an mbuf queue per
 +		 * node and only whacked them into ath_bufs when we
 +		 * are ready to schedule some traffic from them.
 +		 * .. that may come later.
 +		 *
 +		 * XXX we should also track the per-node hardware queue
 +		 * depth so it is easy to limit the _SUM_ of the swq and
 +		 * hwq frames.  Since we only schedule two HWQ frames
 +		 * at a time, this should be OK for now.
 +		 */
 +		if ((!(m->m_flags & M_EAPOL)) &&
 +		    (ATH_NODE(ni)->an_swq_depth > sc->sc_txq_node_maxdepth)) {
 +			sc->sc_stats.ast_tx_nodeq_overflow++;
 +			if (ni != NULL)
 +				ieee80211_free_node(ni);
 +			m_freem(m);
 +			m = NULL;
 +			continue;
 +		}
 +
 +		/*
 +		 * Check how many TX buffers are available.
 +		 *
 +		 * If this is for non-EAPOL traffic, just leave some
 +		 * space free in order for buffer cloning and raw
 +		 * frame transmission to occur.
 +		 *
 +		 * If it's for EAPOL traffic, ignore this for now.
 +		 * Management traffic will be sent via the raw transmit
 +		 * method which bypasses this check.
 +		 *
 +		 * This is needed to ensure that EAPOL frames during
 +		 * (re) keying have a chance to go out.
 +		 *
 +		 * See kern/138379 for more information.
 +		 */
 +		if ((!(m->m_flags & M_EAPOL)) &&
 +		    (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree)) {
 +			sc->sc_stats.ast_tx_nobuf++;
  			IF_LOCK(&ifp->if_snd);
 +			_IF_PREPEND(&ifp->if_snd, m);
  			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  			IF_UNLOCK(&ifp->if_snd);
 +			m = NULL;
  			break;
  		}
 -		ATH_TXBUF_UNLOCK(sc);
 -		
 +
  		/*
  		 * Grab a TX buffer and associated resources.
 +		 *
 +		 * If it's an EAPOL frame, allocate a MGMT ath_buf.
 +		 * That way even with temporary buffer exhaustion due to
 +		 * the data path doesn't leave us without the ability
 +		 * to transmit management frames.
 +		 *
 +		 * Otherwise allocate a normal buffer.
  		 */
 -		bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
 -		if (bf == NULL)
 -			break;
 +		if (m->m_flags & M_EAPOL)
 +			bf = ath_getbuf(sc, ATH_BUFTYPE_MGMT);
 +		else
 +			bf = ath_getbuf(sc, ATH_BUFTYPE_NORMAL);
  
 -		IFQ_DEQUEUE(&ifp->if_snd, m);
 -		if (m == NULL) {
 -			ATH_TXBUF_LOCK(sc);
 -			ath_returnbuf_head(sc, bf);
 -			ATH_TXBUF_UNLOCK(sc);
 +		if (bf == NULL) {
 +			/*
 +			 * If we failed to allocate a buffer, prepend it
 +			 * and continue.
 +			 *
 +			 * We shouldn't fail normally, due to the check
 +			 * above.
 +			 */
 +			sc->sc_stats.ast_tx_nobuf++;
 +			IF_LOCK(&ifp->if_snd);
 +			_IF_PREPEND(&ifp->if_snd, m);
 +			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 +			IF_UNLOCK(&ifp->if_snd);
 +			m = NULL;
  			break;
  		}
 -		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
 +
  		npkts ++;
 +
  		/*
  		 * Check for fragmentation.  If this frame
  		 * has been broken up verify we have enough
 
 Modified: head/sys/dev/ath/if_ath_sysctl.c
 ==============================================================================
 --- head/sys/dev/ath/if_ath_sysctl.c	Tue May  7 07:44:07 2013	(r250325)
 +++ head/sys/dev/ath/if_ath_sysctl.c	Tue May  7 07:52:18 2013	(r250326)
 @@ -748,11 +748,14 @@ ath_sysctlattach(struct ath_softc *sc)
  		"txq_data_minfree", CTLFLAG_RW, &sc->sc_txq_data_minfree,
  		0, "Minimum free buffers before adding a data frame"
  		" to the TX queue");
 -
  	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
  		"txq_mcastq_maxdepth", CTLFLAG_RW,
  		&sc->sc_txq_mcastq_maxdepth, 0,
  		"Maximum buffer depth for multicast/broadcast frames");
 +	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 +		"txq_node_maxdepth", CTLFLAG_RW,
 +		&sc->sc_txq_node_maxdepth, 0,
 +		"Maximum buffer depth for a single node");
  
  #if 0
  	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
 
 Modified: head/sys/dev/ath/if_athioctl.h
 ==============================================================================
 --- head/sys/dev/ath/if_athioctl.h	Tue May  7 07:44:07 2013	(r250325)
 +++ head/sys/dev/ath/if_athioctl.h	Tue May  7 07:52:18 2013	(r250326)
 @@ -163,8 +163,9 @@ struct ath_stats {
  	u_int32_t	ast_tx_mcastq_overflow;	/* multicast queue overflow */
  	u_int32_t	ast_rx_keymiss;
  	u_int32_t	ast_tx_swfiltered;
 +	u_int32_t	ast_tx_nodeq_overflow;	/* node sw queue overflow */
  
 -	u_int32_t	ast_pad[15];
 +	u_int32_t	ast_pad[14];
  };
  
  #define	SIOCGATHSTATS	_IOWR('i', 137, struct ifreq)
 
 Modified: head/sys/dev/ath/if_athvar.h
 ==============================================================================
 --- head/sys/dev/ath/if_athvar.h	Tue May  7 07:44:07 2013	(r250325)
 +++ head/sys/dev/ath/if_athvar.h	Tue May  7 07:52:18 2013	(r250326)
 @@ -799,6 +799,7 @@ struct ath_softc {
  	 *
  	 * + mcastq_maxdepth is the maximum depth allowed of the cabq.
  	 */
 +	int			sc_txq_node_maxdepth;
  	int			sc_txq_data_minfree;
  	int			sc_txq_mcastq_maxdepth;
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
