From patchwork Sat Jul 2 10:59:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liping Zhang X-Patchwork-Id: 643455 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3rhVg01XM8z9s9G for ; Sat, 2 Jul 2016 21:00:12 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=163.com header.i=@163.com header.b=JydXTBDK; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751332AbcGBLAK (ORCPT ); Sat, 2 Jul 2016 07:00:10 -0400 Received: from m12-16.163.com ([220.181.12.16]:58571 "EHLO m12-16.163.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750987AbcGBLAI (ORCPT ); Sat, 2 Jul 2016 07:00:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-Id; bh=486/l0SON0HU+X+CjW LM4pBUSwv9rnvr6j4WOv4wcAU=; b=JydXTBDKeJjQYTOvG5ZbCyxSmHeEicY4sK 7FzV1/R+3EYg1WpSa8wWnskj2QS2LL52fXq4gPDohk0a1lXci4hBrage/Db7ie1v aP5Uv9kJT51nevrrrQjy231f2sQvcNmqmioz4+cuByGoGxJFUIYXJwtYtakbE+qa QiW82bOcA= Received: from MiWiFi-R2D-srv.localdomain (unknown [180.170.252.41]) by smtp12 (Coremail) with SMTP id EMCowABXmaWnnndXXtNsAg--.15306S4; Sat, 02 Jul 2016 19:00:02 +0800 (CST) From: Liping Zhang To: pablo@netfilter.org Cc: netfilter-devel@vger.kernel.org, Liping Zhang Subject: [PATCH nf 2/3] netfilter: cttimeout: unlink timeout obj again when hash resize happen Date: Sat, 2 Jul 2016 18:59:26 +0800 Message-Id: <1467457167-5363-3-git-send-email-zlpnobody@163.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1467457167-5363-1-git-send-email-zlpnobody@163.com> References: <1467457167-5363-1-git-send-email-zlpnobody@163.com> X-CM-TRANSID: EMCowABXmaWnnndXXtNsAg--.15306S4 X-Coremail-Antispam: 1Uf129KBjvJXoW7ur4UZF45Kw4UKw13AF15XFb_yoW8ZrW7pa 95K34fJrWxXFsIvaykK3s7ZFWYyws3uw4Y9r98Wa4rA3Z8twn5Kr48KrW2va43Jrs7Jr43 ZF4j9w13CF1rAw7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jkEf5UUUUU= X-Originating-IP: [180.170.252.41] X-CM-SenderInfo: x2os00perg5qqrwthudrp/1tbiNhOal1WBSupMAQAAsR Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org From: Liping Zhang Imagine such situation, nf_conntrack_htable_size now is 4096, we are doing ctnl_untimeout, and iterate on 3000# bucket. Meanwhile, another user try to reduce hash size to 2048, then all nf_conn are removed to the new hashtable. When this hash resize operation finished, we still try to itreate ct begin from 3000# bucket, find nothing to do and just return. Then we may miss unlinking some timeout objects. And later we will end up with invalid references to timeout object that are already gone. So when we find that hash resize happened, try to unlink timeout objects from the 0# bucket again. Signed-off-by: Liping Zhang --- net/netfilter/nfnetlink_cttimeout.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index 3c84f14..1d0bc86 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -303,16 +303,26 @@ static void ctnl_untimeout(struct net *net, struct ctnl_timeout *timeout) { struct nf_conntrack_tuple_hash *h; const struct hlist_nulls_node *nn; + unsigned int sequence; + spinlock_t *lock; int i; local_bh_disable(); +restart: + sequence = read_seqcount_begin(&nf_conntrack_generation); for (i = 0; i < nf_conntrack_htable_size; i++) { - nf_conntrack_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); + lock = &nf_conntrack_locks[i % CONNTRACK_LOCKS]; + nf_conntrack_lock(lock); + if (read_seqcount_retry(&nf_conntrack_generation, sequence)) { + spin_unlock(lock); + goto restart; + } + if (i < nf_conntrack_htable_size) { hlist_nulls_for_each_entry(h, nn, &nf_conntrack_hash[i], hnnode) untimeout(h, timeout); } - spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); + spin_unlock(lock); } local_bh_enable(); }