From patchwork Thu Mar 12 11:07:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 449383 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 8C3951400DD for ; Thu, 12 Mar 2015 22:07:57 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753165AbbCLLHw (ORCPT ); Thu, 12 Mar 2015 07:07:52 -0400 Received: from ringil.hengli.com.au ([178.18.16.133]:43481 "EHLO ringil.hengli.com.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752235AbbCLLHw (ORCPT ); Thu, 12 Mar 2015 07:07:52 -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 1YW0xy-0003bq-6h; Thu, 12 Mar 2015 22:07:50 +1100 Received: from herbert by gondolin.me.apana.org.au with local (Exim 4.80) (envelope-from ) id 1YW0xx-00051O-RT; Thu, 12 Mar 2015 22:07:49 +1100 Date: Thu, 12 Mar 2015 22:07:49 +1100 From: Herbert Xu To: Thomas Graf , netdev@vger.kernel.org Subject: rhashtable: Fix reader/rehash race Message-ID: <20150312110749.GA19285@gondor.apana.org.au> MIME-Version: 1.0 Content-Disposition: inline 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 There is a potential race condition between readers and the rehasher. In particular, the rehasher could have started a rehash while the reader finishes a scan of the old table but fails to see the new table pointer. This patch closes this window by adding smp_wmb/smp_rmb. Signed-off-by: Herbert Xu diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 6ffc793..68210cc 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -271,6 +271,9 @@ static void rhashtable_rehash(struct rhashtable *ht, */ rcu_assign_pointer(ht->future_tbl, new_tbl); + /* Ensure the new table is visible to readers. */ + smp_wmb(); + for (old_hash = 0; old_hash < old_tbl->size; old_hash++) rhashtable_rehash_chain(ht, old_hash); @@ -618,6 +621,9 @@ restart: return rht_obj(ht, he); } + /* Ensure we see any new tables. */ + smp_rmb(); + old_tbl = tbl; tbl = rht_dereference_rcu(ht->future_tbl, ht); if (unlikely(tbl != old_tbl))