From patchwork Fri Jun 16 17:47:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Wang X-Patchwork-Id: 776908 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3wq7CG61D6z9s8N for ; Sat, 17 Jun 2017 03:48:42 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ZhL37K18"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752616AbdFPRsl (ORCPT ); Fri, 16 Jun 2017 13:48:41 -0400 Received: from mail-pf0-f194.google.com ([209.85.192.194]:33467 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752548AbdFPRsj (ORCPT ); Fri, 16 Jun 2017 13:48:39 -0400 Received: by mail-pf0-f194.google.com with SMTP id w12so7568506pfk.0 for ; Fri, 16 Jun 2017 10:48:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=p1XkZeHeu53gIm4cwVGS2GvM6v5+jlJUSa0smWoJrOU=; b=ZhL37K18SriAn5RQbfRaMxa3Vl9WWxF9FeFpnoTIRduWZk9/UZO4NkUNmCIKaoHFzS eAVm5kOZX/18pKUK8xdonagJ7As768HxXRK3XbKfnFv8MRw0/i9zFrC/3TwEL5y2K2wa bi9hhz4RnhYFeddv4pLoNN/ROBtGRkIDK7IijD4SATW1q8A/Lup/CBXqiArJYyO/riZd 7514lUAq8Kdl3FjUR64ilyO6iCENAWGBIRL24z+zsI5k/wKwgCC/aYT5rY6uHSj8YKd3 xmMAhONxHbwZtZZp58EEPGE2v08i326GbHQfnlQQu9pNnEdElpjLfCS49nNlBe51hN6w MhKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=p1XkZeHeu53gIm4cwVGS2GvM6v5+jlJUSa0smWoJrOU=; b=ST6lR/MXHp8FPjz+55SEDAQ5OCvjSvvIVP7e38DpO1k1wbANtKm5J4JMnEykLd5K2q Q3jliubOIdMaIXECpEjnTF3RmDEmfCsq3ntE929pyLDbNpo/78yDmjiAFHtXWRO7zvEP aDS+O2F0QBCKNH+zD3mXyVKsFY1uiIYcdvqRI8tV9uncx2vwGLaNFT7QuyWY0Z3Xjz+1 G/TlDgwOMMLHcxj329sFJGDdtK7ZZwpXD3yeyrHYaabxwhfeN4jw+vC2y9jRlidZLrz0 9golCn3DE4otXtw3XoxIBGD6qwhOnx3/a22rBTj8yAE9urzAmlDsMcrwEF2ICfvVBq2I oxDQ== X-Gm-Message-State: AKS2vOw6URXg/Ibxh3byLp7ShvluHV1NXdbVr2ec8YzTqiSvlXb2vwWh P6KFfO5lTNxiPg== X-Received: by 10.99.174.5 with SMTP id q5mr12491584pgf.196.1497635313587; Fri, 16 Jun 2017 10:48:33 -0700 (PDT) Received: from weiwan0.mtv.corp.google.com ([100.123.230.66]) by smtp.gmail.com with ESMTPSA id v62sm5292290pfb.124.2017.06.16.10.48.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 16 Jun 2017 10:48:33 -0700 (PDT) From: Wei Wang To: David Miller , netdev@vger.kernel.org Cc: Eric Dumazet , Martin KaFai Lau , Wei Wang Subject: [PATCH net-next 16/21] decnet: take dst->__refcnt when struct dn_route is created Date: Fri, 16 Jun 2017 10:47:39 -0700 Message-Id: <20170616174744.139688-17-tracywwnj@gmail.com> X-Mailer: git-send-email 2.13.1.518.g3df882009-goog In-Reply-To: <20170616174744.139688-1-tracywwnj@gmail.com> References: <20170616174744.139688-1-tracywwnj@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Wei Wang struct dn_route is inserted into dn_rt_hash_table but no dst->__refcnt is taken. This patch makes sure the dn_rt_hash_table's reference to the dst is ref counted. As the dst is always ref counted properly, we can safely mark DST_NOGC flag so dst_release() will release dst based on refcnt only. And dst gc is no longer needed and all dst_free() or its related function calls should be replaced with dst_release() or dst_release_immediate(). And dst_dev_put() is called when removing dst from the hash table to release the reference on dst->dev before we lose pointer to it. Also, correct the logic in dn_dst_check_expire() and dn_dst_gc() to check dst->__refcnt to be > 1 to indicate it is referenced by other users. Signed-off-by: Wei Wang Acked-by: Martin KaFai Lau --- net/decnet/dn_route.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 6f95612b4d32..f467c4e3205b 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -183,11 +183,6 @@ static __inline__ unsigned int dn_hash(__le16 src, __le16 dst) return dn_rt_hash_mask & (unsigned int)tmp; } -static inline void dnrt_free(struct dn_route *rt) -{ - call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); -} - static void dn_dst_check_expire(unsigned long dummy) { int i; @@ -202,14 +197,15 @@ static void dn_dst_check_expire(unsigned long dummy) spin_lock(&dn_rt_hash_table[i].lock); while ((rt = rcu_dereference_protected(*rtp, lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { - if (atomic_read(&rt->dst.__refcnt) || - (now - rt->dst.lastuse) < expire) { + if (atomic_read(&rt->dst.__refcnt) > 1 || + (now - rt->dst.lastuse) < expire) { rtp = &rt->dst.dn_next; continue; } *rtp = rt->dst.dn_next; rt->dst.dn_next = NULL; - dnrt_free(rt); + dst_dev_put(&rt->dst); + dst_release(&rt->dst); } spin_unlock(&dn_rt_hash_table[i].lock); @@ -235,14 +231,15 @@ static int dn_dst_gc(struct dst_ops *ops) while ((rt = rcu_dereference_protected(*rtp, lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { - if (atomic_read(&rt->dst.__refcnt) || - (now - rt->dst.lastuse) < expire) { + if (atomic_read(&rt->dst.__refcnt) > 1 || + (now - rt->dst.lastuse) < expire) { rtp = &rt->dst.dn_next; continue; } *rtp = rt->dst.dn_next; rt->dst.dn_next = NULL; - dnrt_free(rt); + dst_dev_put(&rt->dst); + dst_release(&rt->dst); break; } spin_unlock_bh(&dn_rt_hash_table[i].lock); @@ -344,7 +341,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou dst_use(&rth->dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); - dst_free(&rt->dst); + dst_release_immediate(&rt->dst); *rp = rth; return 0; } @@ -374,7 +371,8 @@ static void dn_run_flush(unsigned long dummy) for(; rt; rt = next) { next = rcu_dereference_raw(rt->dst.dn_next); RCU_INIT_POINTER(rt->dst.dn_next, NULL); - dnrt_free(rt); + dst_dev_put(&rt->dst); + dst_release(&rt->dst); } nothing_to_declare: @@ -1181,7 +1179,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o if (dev_out->flags & IFF_LOOPBACK) flags |= RTCF_LOCAL; - rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST); + rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, + DST_HOST | DST_NOGC); if (rt == NULL) goto e_nobufs; @@ -1215,6 +1214,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o goto e_neighbour; hash = dn_hash(rt->fld.saddr, rt->fld.daddr); + /* dn_insert_route() increments dst->__refcnt */ dn_insert_route(rt, hash, (struct dn_route **)pprt); done: @@ -1237,7 +1237,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o err = -ENOBUFS; goto done; e_neighbour: - dst_free(&rt->dst); + dst_release_immediate(&rt->dst); goto e_nobufs; } @@ -1445,7 +1445,8 @@ static int dn_route_input_slow(struct sk_buff *skb) } make_route: - rt = dst_alloc(&dn_dst_ops, out_dev, 0, DST_OBSOLETE_NONE, DST_HOST); + rt = dst_alloc(&dn_dst_ops, out_dev, 1, DST_OBSOLETE_NONE, + DST_HOST | DST_NOGC); if (rt == NULL) goto e_nobufs; @@ -1491,6 +1492,7 @@ static int dn_route_input_slow(struct sk_buff *skb) goto e_neighbour; hash = dn_hash(rt->fld.saddr, rt->fld.daddr); + /* dn_insert_route() increments dst->__refcnt */ dn_insert_route(rt, hash, &rt); skb_dst_set(skb, &rt->dst); @@ -1514,7 +1516,7 @@ static int dn_route_input_slow(struct sk_buff *skb) goto done; e_neighbour: - dst_free(&rt->dst); + dst_release_immediate(&rt->dst); goto done; }