From owner-svn-src-head@FreeBSD.ORG Fri Sep 28 20:43:04 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 0BBCA106564A; Fri, 28 Sep 2012 20:43:04 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E22D08FC15; Fri, 28 Sep 2012 20:43:03 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q8SKh3Rm003642; Fri, 28 Sep 2012 20:43:03 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8SKh3ls003640; Fri, 28 Sep 2012 20:43:03 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201209282043.q8SKh3ls003640@svn.freebsd.org> From: Gleb Smirnoff Date: Fri, 28 Sep 2012 20:43:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r241039 - head/sys/netpfil/pf X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Sep 2012 20:43:04 -0000 Author: glebius Date: Fri Sep 28 20:43:03 2012 New Revision: 241039 URL: http://svn.freebsd.org/changeset/base/241039 Log: Simplify and somewhat redesign interaction between pf_purge_thread() and pf_purge_expired_states(). Now pf purging daemon stores the current hash table index on stack in pf_purge_thread(), and supplies it to next iteration of pf_purge_expired_states(). The latter returns new index back. The important change is that whenever pf_purge_expired_states() wraps around the array it returns immediately. This makes our knowledge about status of states expiry run more consistent. Prior to this change it could happen that n-th run stopped on i-th entry, and returned (1) as full run complete, then next (n+1) full run stopped on j-th entry, where j < i, and that broke the mark-and-sweep algorythm that saves references rules. A referenced rule was freed, and this later lead to a crash. Modified: head/sys/netpfil/pf/pf.c Modified: head/sys/netpfil/pf/pf.c ============================================================================== --- head/sys/netpfil/pf/pf.c Fri Sep 28 20:29:06 2012 (r241038) +++ head/sys/netpfil/pf/pf.c Fri Sep 28 20:43:03 2012 (r241039) @@ -282,7 +282,7 @@ static int pf_src_connlimit(struct pf_ static void pf_overload_task(void *c, int pending); static int pf_insert_src_node(struct pf_src_node **, struct pf_rule *, struct pf_addr *, sa_family_t); -static int pf_purge_expired_states(int); +static u_int pf_purge_expired_states(u_int, int); static void pf_purge_unlinked_rules(void); static int pf_mtag_init(void *, int, int); static void pf_mtag_free(struct m_tag *); @@ -1307,7 +1307,7 @@ pf_intr(void *v) void pf_purge_thread(void *v) { - int fullrun; + u_int idx = 0; CURVNET_SET((struct vnet *)v); @@ -1329,7 +1329,7 @@ pf_purge_thread(void *v) /* * Now purge everything. */ - pf_purge_expired_states(V_pf_hashmask + 1); + pf_purge_expired_states(0, V_pf_hashmask); pf_purge_expired_fragments(); pf_purge_expired_src_nodes(); @@ -1352,11 +1352,11 @@ pf_purge_thread(void *v) PF_RULES_RUNLOCK(); /* Process 1/interval fraction of the state table every run. */ - fullrun = pf_purge_expired_states(V_pf_hashmask / + idx = pf_purge_expired_states(idx, V_pf_hashmask / (V_pf_default_rule.timeout[PFTM_INTERVAL] * 10)); /* Purge other expired types every PFTM_INTERVAL seconds. */ - if (fullrun) { + if (idx == 0) { /* * Order is important: * - states and src nodes reference rules @@ -1533,14 +1533,11 @@ pf_free_state(struct pf_state *cur) /* * Called only from pf_purge_thread(), thus serialized. */ -static int -pf_purge_expired_states(int maxcheck) +static u_int +pf_purge_expired_states(u_int i, int maxcheck) { - static u_int i = 0; - struct pf_idhash *ih; struct pf_state *s; - int rv = 0; V_pf_status.states = uma_zone_get_cur(V_pf_state_z); @@ -1549,12 +1546,6 @@ pf_purge_expired_states(int maxcheck) */ while (maxcheck > 0) { - /* Wrap to start of hash when we hit the end. */ - if (i > V_pf_hashmask) { - i = 0; - rv = 1; - } - ih = &V_pf_idhash[i]; relock: PF_HASHROW_LOCK(ih); @@ -1574,13 +1565,19 @@ relock: s->rt_kif->pfik_flags |= PFI_IFLAG_REFS; } PF_HASHROW_UNLOCK(ih); - i++; + + /* Return when we hit end of hash. */ + if (++i > V_pf_hashmask) { + V_pf_status.states = uma_zone_get_cur(V_pf_state_z); + return (0); + } + maxcheck--; } V_pf_status.states = uma_zone_get_cur(V_pf_state_z); - return (rv); + return (i); } static void