Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/810846/?format=api
{ "id": 810846, "url": "http://patchwork.ozlabs.org/api/patches/810846/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170907042607.24413-2-xiyou.wangcong@gmail.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170907042607.24413-2-xiyou.wangcong@gmail.com>", "list_archive_url": null, "date": "2017-09-07T04:26:07", "name": "[net,v2,2/2] net_sched: fix all the madness of tc filter chain", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": true, "hash": "b284d1ae955bc5e3f17c412a18615be3031a5df7", "submitter": { "id": 211, "url": "http://patchwork.ozlabs.org/api/people/211/?format=api", "name": "Cong Wang", "email": "xiyou.wangcong@gmail.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170907042607.24413-2-xiyou.wangcong@gmail.com/mbox/", "series": [ { "id": 1909, "url": "http://patchwork.ozlabs.org/api/series/1909/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=1909", "date": "2017-09-07T04:26:06", "name": "[net,v2,1/2] net_sched: get rid of tcfa_rcu", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/1909/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/810846/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/810846/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"aEdhOjgO\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xnnTJ2fw2z9sNd\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 7 Sep 2017 14:26:28 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1753447AbdIGE01 (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tThu, 7 Sep 2017 00:26:27 -0400", "from mail-pf0-f194.google.com ([209.85.192.194]:38719 \"EHLO\n\tmail-pf0-f194.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1753374AbdIGE0S (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Thu, 7 Sep 2017 00:26:18 -0400", "by mail-pf0-f194.google.com with SMTP id q76so3986514pfq.5\n\tfor <netdev@vger.kernel.org>; Wed, 06 Sep 2017 21:26:18 -0700 (PDT)", "from tw-172-25-30-113.office.twttr.net ([8.25.197.25])\n\tby smtp.gmail.com with ESMTPSA id\n\ti2sm1759997pfd.21.2017.09.06.21.26.16\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tWed, 06 Sep 2017 21:26:17 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=QP2ih+6R2zUU3QnYXeel7vXIeTgLdhbU/uqmelCoUag=;\n\tb=aEdhOjgOQv+XaymnOaES961LQcPjbCEvDrI/pe8Yj48jzluplhbaUs9ZsJwVrXVq3w\n\thLM6hp6Iwc0Ae5VC5ET95qRUCvuI80DYKolzo6ZbH5R7ilnn+01Cm7T5Fdjs8yHrT9uO\n\tOslU69PkNEiPvPnp2PWR0BauCb5JBIi5wnkp9S98erm0aBmomR2CVCyxiEm4uw3qGQKV\n\t0gJpm5lhZPGrKIfau08srencn49wqVWTYCqmIoXa3X0HrmpuAsHsU3rfToN7dqkPYJPJ\n\tIp5L4OXa8KDN+PoOz+4Wn/tk3ZASEfvHbQ+DbcDLI+26TqkAUlX3oB/UBM+8pXNIILvB\n\tNobA==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=QP2ih+6R2zUU3QnYXeel7vXIeTgLdhbU/uqmelCoUag=;\n\tb=G+AN0i/V9PDuhA6waY9YFwlqIVsgeJas3EGkmjq45EwEyfCO+ZfyVmDtNaiuAo+qNz\n\tADrFO/3H3wUt+b7PvBu78d7FkLB8ZyYYE8Q55s7HbMiS7Hb1Bu1KpV+4W2Gpx1UQvjnb\n\te7yQNlJPEeYmz6UcuzpVWCjHMGoOdaSgb5Xdr/asTV1IAJLx6NCzXWIBmUaiTK7M4nHO\n\tLaqKiyunE3nesV2E+UmAy8b94tdUiK0FMM2LfpmKujAt+TqbbookD/fHGk2vMx2+U9ji\n\tD2aBu2wAasbXWnnuDqNhmdlnyNEjU9mnUw+EMdsKOiWJ4PvspE/FfNeDqFpdKYX+u9KV\n\ts1xg==", "X-Gm-Message-State": "AHPjjUgK9G7yYYYWOUb6KjzZrU3T2SsFYu31+OatXTWNhV9Tr5U3eGQ3\n\teb5nVAcHhcTXfUEkHgs=", "X-Google-Smtp-Source": "ADKCNb5f0aqpHkgAO5RUrvV17ZKYec2Wguv3bAD4LVXcNnNM1Mr10YF2zIkdCn7n07j0DPq4aeA2CQ==", "X-Received": "by 10.84.129.226 with SMTP id b89mr1571237plb.84.1504758377895; \n\tWed, 06 Sep 2017 21:26:17 -0700 (PDT)", "From": "Cong Wang <xiyou.wangcong@gmail.com>", "To": "netdev@vger.kernel.org", "Cc": "jakub.kicinski@netronome.com, Cong Wang <xiyou.wangcong@gmail.com>,\n\tJiri Pirko <jiri@mellanox.com>", "Subject": "[Patch net v2 2/2] net_sched: fix all the madness of tc filter chain", "Date": "Wed, 6 Sep 2017 21:26:07 -0700", "Message-Id": "<20170907042607.24413-2-xiyou.wangcong@gmail.com>", "X-Mailer": "git-send-email 2.9.4", "In-Reply-To": "<20170907042607.24413-1-xiyou.wangcong@gmail.com>", "References": "<20170907042607.24413-1-xiyou.wangcong@gmail.com>", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "This patch fixes the following madness of tc filter chain:\n\n1) tcf_chain_destroy() is called by both tcf_block_put() and\n tcf_chain_put(). tcf_chain_put() is correctly refcnt'ed and paired\n with tcf_chain_get(), but tcf_block_put() is not, it should be paired\n with tcf_block_get() which means we still need to decrease the refcnt.\n Think it in another way: if we call tcf_bock_put() immediately after\n tcf_block_get(), could we get effectively a nop? This causes a memory\n leak as reported by Jakub.\n\n2) tp proto should hold a refcnt to the chain too. This significantly\n simplifies the logic:\n\n2a) Chain 0 is no longer special, it is created and refcnted by tp\n like any other chains. All the ugliness in tcf_chain_put() can be\n gone!\n\n2b) No need to handle the flushing oddly, because block still holds\n chain 0, it can not be released, this guarantees block is the last\n user.\n\n2c) The race condition with RCU callbacks is easier to handle with just\n a rcu_barrier()! Much easier to understand, nothing to hide! Thanks\n to the previous patch. Please see also the comments in code.\n\n2d) Make the code understandable by humans, much less error-prone.\n\nFixes: 744a4cf63e52 (\"net: sched: fix use after free when tcf_chain_destroy is called multiple times\")\nFixes: 5bc1701881e3 (\"net: sched: introduce multichain support for filters\")\nReported-by: Jakub Kicinski <jakub.kicinski@netronome.com>\nCc: Jiri Pirko <jiri@mellanox.com>\nSigned-off-by: Cong Wang <xiyou.wangcong@gmail.com>\n---\n net/sched/cls_api.c | 38 ++++++++++++++++++++++----------------\n 1 file changed, 22 insertions(+), 16 deletions(-)", "diff": "diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c\nindex 6c5ea84d2682..e9060dc36519 100644\n--- a/net/sched/cls_api.c\n+++ b/net/sched/cls_api.c\n@@ -209,21 +209,20 @@ static void tcf_chain_flush(struct tcf_chain *chain)\n \t\tRCU_INIT_POINTER(*chain->p_filter_chain, NULL);\n \twhile ((tp = rtnl_dereference(chain->filter_chain)) != NULL) {\n \t\tRCU_INIT_POINTER(chain->filter_chain, tp->next);\n+\t\ttcf_chain_put(chain);\n \t\ttcf_proto_destroy(tp);\n \t}\n }\n \n static void tcf_chain_destroy(struct tcf_chain *chain)\n {\n-\t/* May be already removed from the list by the previous call. */\n-\tif (!list_empty(&chain->list))\n-\t\tlist_del_init(&chain->list);\n+\tlist_del(&chain->list);\n+\tkfree(chain);\n+}\n \n-\t/* There might still be a reference held when we got here from\n-\t * tcf_block_put. Wait for the user to drop reference before free.\n-\t */\n-\tif (!chain->refcnt)\n-\t\tkfree(chain);\n+static void tcf_chain_hold(struct tcf_chain *chain)\n+{\n+\t++chain->refcnt;\n }\n \n struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,\n@@ -233,7 +232,7 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,\n \n \tlist_for_each_entry(chain, &block->chain_list, list) {\n \t\tif (chain->index == chain_index) {\n-\t\t\tchain->refcnt++;\n+\t\t\ttcf_chain_hold(chain);\n \t\t\treturn chain;\n \t\t}\n \t}\n@@ -246,10 +245,7 @@ EXPORT_SYMBOL(tcf_chain_get);\n \n void tcf_chain_put(struct tcf_chain *chain)\n {\n-\t/* Destroy unused chain, with exception of chain 0, which is the\n-\t * default one and has to be always present.\n-\t */\n-\tif (--chain->refcnt == 0 && !chain->filter_chain && chain->index != 0)\n+\tif (--chain->refcnt == 0)\n \t\ttcf_chain_destroy(chain);\n }\n EXPORT_SYMBOL(tcf_chain_put);\n@@ -294,10 +290,18 @@ void tcf_block_put(struct tcf_block *block)\n \tif (!block)\n \t\treturn;\n \n-\tlist_for_each_entry_safe(chain, tmp, &block->chain_list, list) {\n+\t/* Standalone actions are not allowed to jump to any chain, and\n+\t * bound actions should be all removed after flushing. However,\n+\t * filters are destroyed in RCU callbacks, we have to flush and wait\n+\t * for them before releasing this refcnt, otherwise we race with RCU\n+\t * callbacks!!!\n+\t */\n+\tlist_for_each_entry(chain, &block->chain_list, list)\n \t\ttcf_chain_flush(chain);\n-\t\ttcf_chain_destroy(chain);\n-\t}\n+\trcu_barrier();\n+\n+\tlist_for_each_entry_safe(chain, tmp, &block->chain_list, list)\n+\t\ttcf_chain_put(chain);\n \tkfree(block);\n }\n EXPORT_SYMBOL(tcf_block_put);\n@@ -375,6 +379,7 @@ static void tcf_chain_tp_insert(struct tcf_chain *chain,\n \t\trcu_assign_pointer(*chain->p_filter_chain, tp);\n \tRCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain_info));\n \trcu_assign_pointer(*chain_info->pprev, tp);\n+\ttcf_chain_hold(chain);\n }\n \n static void tcf_chain_tp_remove(struct tcf_chain *chain,\n@@ -386,6 +391,7 @@ static void tcf_chain_tp_remove(struct tcf_chain *chain,\n \tif (chain->p_filter_chain && tp == chain->filter_chain)\n \t\tRCU_INIT_POINTER(*chain->p_filter_chain, next);\n \tRCU_INIT_POINTER(*chain_info->pprev, next);\n+\ttcf_chain_put(chain);\n }\n \n static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,\n", "prefixes": [ "net", "v2", "2/2" ] }