From patchwork Sat Apr 6 12:17:16 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pablo Neira Ayuso X-Patchwork-Id: 234336 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 33B432C0100 for ; Sat, 6 Apr 2013 23:18:33 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1163412Ab3DFMSa (ORCPT ); Sat, 6 Apr 2013 08:18:30 -0400 Received: from mail.us.es ([193.147.175.20]:38928 "EHLO mail.us.es" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1163392Ab3DFMS0 (ORCPT ); Sat, 6 Apr 2013 08:18:26 -0400 Received: (qmail 28896 invoked from network); 6 Apr 2013 14:18:25 +0200 Received: from unknown (HELO us.es) (192.168.2.12) by us.es with SMTP; 6 Apr 2013 14:18:25 +0200 Received: (qmail 5511 invoked by uid 507); 6 Apr 2013 12:18:25 -0000 X-Qmail-Scanner-Diagnostics: from 127.0.0.1 by antivirus2 (envelope-from , uid 501) with qmail-scanner-2.10 (clamdscan: 0.97.7/16967. spamassassin: 3.3.2. Clear:RC:1(127.0.0.1):SA:0(-98.6/7.5):. Processed in 4.25099 secs); 06 Apr 2013 12:18:25 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on antivirus2 X-Spam-Level: X-Spam-Status: No, score=-98.6 required=7.5 tests=BAYES_50, RCVD_IN_SORBS_DUL, USER_IN_WHITELIST autolearn=disabled version=3.3.2 X-Envelope-From: pablo@netfilter.org Received: from unknown (HELO antivirus2) (127.0.0.1) by us.es with SMTP; 6 Apr 2013 12:18:20 -0000 Received: from 192.168.1.13 (192.168.1.13) by antivirus2 (F-Secure/fsigk_smtp/407/antivirus2); Sat, 06 Apr 2013 14:18:20 +0200 (CEST) X-Virus-Status: clean(F-Secure/fsigk_smtp/407/antivirus2) Received: (qmail 7047 invoked from network); 6 Apr 2013 14:18:20 +0200 Received: from dhcp103.vr.in-berlin.de (HELO soleta.in-berlin.de) (pneira@us.es@217.197.81.103) by us.es with SMTP; 6 Apr 2013 14:18:20 +0200 From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Cc: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH 17/51] ipvs: add ip_vs_dest_hold and ip_vs_dest_put Date: Sat, 6 Apr 2013 14:17:16 +0200 Message-Id: <1365250670-14993-18-git-send-email-pablo@netfilter.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1365250670-14993-1-git-send-email-pablo@netfilter.org> References: <1365250670-14993-1-git-send-email-pablo@netfilter.org> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Julian Anastasov ip_vs_dest_hold will be used under RCU lock while ip_vs_dest_put can be called even after dest is removed from service, as it happens for conns and some schedulers. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman --- include/net/ip_vs.h | 10 ++++++++++ net/netfilter/ipvs/ip_vs_conn.c | 9 ++------- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++-- net/netfilter/ipvs/ip_vs_sync.c | 4 ++-- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index d91385c..7d3027f 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1427,6 +1427,16 @@ ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr, __u16 protocol, __u32 fwmark, __u32 flags); extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); +static inline void ip_vs_dest_hold(struct ip_vs_dest *dest) +{ + atomic_inc(&dest->refcnt); +} + +static inline void ip_vs_dest_put(struct ip_vs_dest *dest) +{ + smp_mb__before_atomic_dec(); + atomic_dec(&dest->refcnt); +} /* * IPVS sync daemon data and function prototypes diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index e3e2b4d..1b29e4a 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -554,7 +554,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) return; /* Increase the refcnt counter of the dest */ - atomic_inc(&dest->refcnt); + ip_vs_dest_hold(dest); conn_flags = atomic_read(&dest->conn_flags); if (cp->protocol != IPPROTO_UDP) @@ -700,12 +700,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) dest->flags &= ~IP_VS_DEST_F_OVERLOAD; } - /* - * Simply decrease the refcnt of the dest, because the - * dest will be either in service's destination list - * or in the trash. - */ - atomic_dec(&dest->refcnt); + ip_vs_dest_put(dest); } static int expire_quiescent_template(struct netns_ipvs *ipvs, diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index d64f800..a4f6388 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -616,7 +616,7 @@ struct ip_vs_dest *ip_vs_find_dest(struct net *net, int af, if (!dest) dest = ip_vs_lookup_dest(svc, daddr, port ^ dport); if (dest) - atomic_inc(&dest->refcnt); + ip_vs_dest_hold(dest); ip_vs_service_put(svc); return dest; } @@ -1056,7 +1056,7 @@ static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest) ntohs(dest->port), atomic_read(&dest->refcnt)); list_add(&dest->n_list, &ipvs->dest_trash); - atomic_inc(&dest->refcnt); + ip_vs_dest_hold(dest); } } diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 44fd10c..6cc3e52 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -861,7 +861,7 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, if (!dest) { dest = ip_vs_try_bind_dest(cp); if (dest) - atomic_dec(&dest->refcnt); + ip_vs_dest_put(dest); } } else { /* @@ -874,7 +874,7 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); if (dest) - atomic_dec(&dest->refcnt); + ip_vs_dest_put(dest); if (!cp) { if (param->pe_data) kfree(param->pe_data);