From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vlad Buslov Subject: [PATCH net-next 17/17] net: sched: unlock rules update API Date: Mon, 12 Nov 2018 09:55:46 +0200 Message-ID: <1542009346-23780-18-git-send-email-vladbu@mellanox.com> References: <1542009346-23780-1-git-send-email-vladbu@mellanox.com> Cc: jhs@mojatatu.com, xiyou.wangcong@gmail.com, jiri@resnulli.us, davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Vlad Buslov To: netdev@vger.kernel.org Return-path: Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:55013 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728396AbeKLRsA (ORCPT ); Mon, 12 Nov 2018 12:48:00 -0500 In-Reply-To: <1542009346-23780-1-git-send-email-vladbu@mellanox.com> Sender: netdev-owner@vger.kernel.org List-ID: Register netlink protocol handlers for message types RTM_NEWTFILTER, RTM_DELTFILTER, RTM_GETTFILTER as unlocked. Set rtnl_held variable that tracks rtnl mutex state to be false by default. Modify tcf_block_release() to release rtnl lock if it was taken before. Move code that releases block and qdisc to function __tcf_block_release() that is used internally by regular block release and by chain update function, which is not unlocked and doesn't need to release rtnl. Signed-off-by: Vlad Buslov Acked-by: Jiri Pirko --- net/sched/cls_api.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 848f148f1019..a23aeac8ea4e 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1024,13 +1024,28 @@ static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q, return ERR_PTR(err); } -static void tcf_block_release(struct Qdisc *q, struct tcf_block *block) +static void __tcf_block_release(struct Qdisc *q, struct tcf_block *block, + bool rtnl_held) { if (!IS_ERR_OR_NULL(block)) tcf_block_refcnt_put(block); - if (q) - qdisc_put(q); + if (q) { + if (rtnl_held) + qdisc_put(q); + else + qdisc_put_unlocked(q); + } +} + +static void tcf_block_release(struct Qdisc *q, struct tcf_block *block, + bool *rtnl_held) +{ + if (*rtnl_held) { + rtnl_unlock(); + *rtnl_held = false; + } + __tcf_block_release(q, block, false); } struct tcf_block_owner_item { @@ -1706,7 +1721,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *fh; int err; int tp_created; - bool rtnl_held = true; + bool rtnl_held = false; if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) return -EPERM; @@ -1865,7 +1880,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, if (!tp_created) tcf_chain_put(chain); } - tcf_block_release(q, block); + tcf_block_release(q, block, &rtnl_held); if (err == -EAGAIN) { /* Take rtnl lock in case EAGAIN is caused by concurrent flush * of target chain. @@ -1899,7 +1914,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, unsigned long cl = 0; void *fh = NULL; int err; - bool rtnl_held = true; + bool rtnl_held = false; if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) return -EPERM; @@ -2011,7 +2026,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n, tcf_proto_put(tp, NULL); tcf_chain_put(chain); } - tcf_block_release(q, block); + tcf_block_release(q, block, &rtnl_held); return err; errout_locked: @@ -2037,7 +2052,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, unsigned long cl = 0; void *fh = NULL; int err; - bool rtnl_held = true; + bool rtnl_held = false; err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, rtm_tca_policy, extack); if (err < 0) @@ -2112,7 +2127,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n, tcf_proto_put(tp, NULL); tcf_chain_put(chain); } - tcf_block_release(q, block); + tcf_block_release(q, block, &rtnl_held); return err; } @@ -2561,7 +2576,7 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n, errout: tcf_chain_put(chain); errout_block: - tcf_block_release(q, block); + __tcf_block_release(q, block, true); if (err == -EAGAIN) /* Replay the request. */ goto replay; @@ -2899,10 +2914,12 @@ static int __init tc_filter_init(void) if (err) goto err_register_pernet_subsys; - rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL, 0); - rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_del_tfilter, NULL, 0); + rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL, + RTNL_FLAG_DOIT_UNLOCKED); + rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_del_tfilter, NULL, + RTNL_FLAG_DOIT_UNLOCKED); rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_get_tfilter, - tc_dump_tfilter, 0); + tc_dump_tfilter, RTNL_FLAG_DOIT_UNLOCKED); rtnl_register(PF_UNSPEC, RTM_NEWCHAIN, tc_ctl_chain, NULL, 0); rtnl_register(PF_UNSPEC, RTM_DELCHAIN, tc_ctl_chain, NULL, 0); rtnl_register(PF_UNSPEC, RTM_GETCHAIN, tc_ctl_chain, -- 2.7.5