From patchwork Sat Jun 17 17:42: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: 777354 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 3wql3Z3clxz9s76 for ; Sun, 18 Jun 2017 03:44:10 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QZiek+nF"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752865AbdFQRoF (ORCPT ); Sat, 17 Jun 2017 13:44:05 -0400 Received: from mail-pg0-f66.google.com ([74.125.83.66]:35489 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752824AbdFQRoC (ORCPT ); Sat, 17 Jun 2017 13:44:02 -0400 Received: by mail-pg0-f66.google.com with SMTP id f127so10586479pgc.2 for ; Sat, 17 Jun 2017 10:43:57 -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=QZiek+nFobrPdF6xz8S2jbVK511Xt0+83coaT61RhOLK3JVoyxUAjH2pM76gw+NdDR gVyqD2S3nF+IG9VPu4ZlTMIsNdks7R0afj6wQm0PJAd48r16x9WbH2muqUh9R7+4EJwu 02Td6j9wPLkLyj6b2PdltfjaP45icrSakUrfiLZ5VQVAjC8VCp1FYFaMsADA6JTZiTCM Jw6DHfsOz/UNLvkgRGzfJmeqBt8ZzsMQbwXlIOWN+5vYyeXL19fYib+FZCtDRB0JbMVL iH1jkn7X8BqoTRxm82b/W6uflD3hgtulP4z+fXxbYlh7pVeTqKZ4afhT2xybfq43DIo6 ABMA== 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=dSL4lc5hsMf5Oyu2uzeGSQ3Qzvhp+lgp2XdOhbrRCFq/CBVZNAnSgMShNKcYjakTWy K2WwYKDg5u0uxEQMiXTakvbjmGExbmktkiiyJWHEaRwZ0VPHDlsXSSqTM9yoTIbvyNjL EftUdI5KCNeXUm8U3EJYcWwrlHFz/U4yvZxQZFAkVYRhzwqWSNFvNC0PPgFySTCpdxPa /ZHQpZuQ1TNJpeBvPRqbJl4SCkcf8PwiG5i7y1nJ0t9r566KanhPv76gmL8R4JeWvaWj odPoY+y3yhIuuwnYTriB9ZlvuU5hB+mBjN1AG9ohqOz6O1cfWzkwfZYzDqLQOI2h7Cu2 QWUw== X-Gm-Message-State: AKS2vOwdMRlJV80h4Y829USx6f4F6SfGYWiT8LFFaXwoKg6/hijZ9uwT hXRL8FKvaqsTKZRBx4M= X-Received: by 10.99.126.67 with SMTP id o3mr17460006pgn.36.1497721426239; Sat, 17 Jun 2017 10:43:46 -0700 (PDT) Received: from weiwan0.mtv.corp.google.com ([100.123.230.66]) by smtp.gmail.com with ESMTPSA id h7sm11352777pfc.97.2017.06.17.10.43.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 17 Jun 2017 10:43:45 -0700 (PDT) From: Wei Wang To: David Miller , netdev@vger.kernel.org Cc: Eric Dumazet , Martin KaFai Lau , Wei Wang Subject: [PATCH v2 net-next 16/21] decnet: take dst->__refcnt when struct dn_route is created Date: Sat, 17 Jun 2017 10:42:39 -0700 Message-Id: <20170617174244.132862-17-tracywwnj@gmail.com> X-Mailer: git-send-email 2.13.1.518.g3df882009-goog In-Reply-To: <20170617174244.132862-1-tracywwnj@gmail.com> References: <20170617174244.132862-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; }