From patchwork Sun May 17 02:45:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 473111 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 E26E1140B04 for ; Sun, 17 May 2015 12:45:56 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751104AbbEQCpp (ORCPT ); Sat, 16 May 2015 22:45:45 -0400 Received: from helcar.hengli.com.au ([209.40.204.226]:39211 "EHLO helcar.hengli.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750774AbbEQCpo (ORCPT ); Sat, 16 May 2015 22:45:44 -0400 Received: from gondolin.me.apana.org.au ([192.168.0.6]) by norbury.hengli.com.au with esmtp (Exim 4.80 #3 (Debian)) id 1YtoaA-0003Tg-Bq; Sun, 17 May 2015 12:45:38 +1000 Received: from herbert by gondolin.me.apana.org.au with local (Exim 4.80) (envelope-from ) id 1Ytoa7-0001Ta-1G; Sun, 17 May 2015 10:45:35 +0800 Date: Sun, 17 May 2015 10:45:34 +0800 From: Herbert Xu To: David Miller Cc: eric.dumazet@gmail.com, tgraf@suug.ch, netdev@vger.kernel.org, ying.xue@windriver.com Subject: [net-next] netlink: Use random autobind rover Message-ID: <20150517024534.GA5570@gondor.apana.org.au> References: <20150515.130219.331336809636676892.davem@redhat.com> <20150516123242.GA683@gondor.apana.org.au> <20150516134007.GA1152@gondor.apana.org.au> <20150516.170819.1082459707799000658.davem@davemloft.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20150516.170819.1082459707799000658.davem@davemloft.net> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On Sat, May 16, 2015 at 05:08:19PM -0400, David Miller wrote: > > As far as I can tell, this ought to be fine as-is. OK what about dropping the global rover altogether? Let's just start randomly like UDP. ---8<--- Currently we use a global rover to select a port ID that is unique. This used to work consistently when it was protected with a global lock. However as we're now lockless, the global rover can exhibit pathological behaviour should multiple threads all stomp on it at the same time. Granted this will eventually resolve itself but the process is suboptimal. This patch replaces the global rover with a pseudorandom starting point to avoid this issue. Signed-off-by: Herbert Xu diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index ec4adbd..716c6d2 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1296,20 +1296,24 @@ static int netlink_autobind(struct socket *sock) struct netlink_table *table = &nl_table[sk->sk_protocol]; s32 portid = task_tgid_vnr(current); int err; - static s32 rover = -4097; + s32 rover = -4096; + bool ok; retry: cond_resched(); rcu_read_lock(); - if (__netlink_lookup(table, portid, net)) { + ok = !__netlink_lookup(table, portid, net); + rcu_read_unlock(); + if (!ok) { /* Bind collision, search negative portid values. */ - portid = rover--; - if (rover > -4097) + if (rover == -4096) + /* rover will be in range [S32_MIN, -4097] */ + rover = S32_MIN + prandom_u32_max(-4096 - S32_MIN); + else if (rover >= -4096) rover = -4097; - rcu_read_unlock(); + portid = rover--; goto retry; } - rcu_read_unlock(); err = netlink_insert(sk, portid); if (err == -EADDRINUSE)