From patchwork Sat Jan 31 09:36:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 435113 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 BE20A1402CF for ; Sat, 31 Jan 2015 20:36:49 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752740AbbAaJgp (ORCPT ); Sat, 31 Jan 2015 04:36:45 -0500 Received: from helcar.apana.org.au ([209.40.204.226]:57178 "EHLO helcar.apana.org.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751783AbbAaJgm (ORCPT ); Sat, 31 Jan 2015 04:36:42 -0500 Received: from gondolin.me.apana.org.au ([192.168.0.6]) by norbury.hengli.com.au with esmtp (Exim 4.80 #3 (Debian)) id 1YHUTo-0007VX-7l; Sat, 31 Jan 2015 20:36:40 +1100 Received: from herbert by gondolin.me.apana.org.au with local (Exim 4.80) (envelope-from ) id 1YHUTm-0007bM-Fc; Sat, 31 Jan 2015 20:36:38 +1100 Date: Sat, 31 Jan 2015 20:36:38 +1100 From: Herbert Xu To: Thomas Graf , netdev@vger.kernel.org Subject: rhashtable: Fix potential crash on destroy in rhashtable_shrink Message-ID: <20150131093637.GA29106@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 The current being_destroyed check in rhashtable_expand is not enough since if we start a shrinking process after freeing all elements in the table that's also going to crash. This patch adds a being_destroyed check to the deferred worker thread so that we bail out as soon as we take the lock. Signed-off-by: Herbert Xu Acked-by: Thomas Graf diff --git a/lib/rhashtable.c b/lib/rhashtable.c index 69a4eb0..4c3da1f 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -489,6 +489,9 @@ static void rht_deferred_worker(struct work_struct *work) ht = container_of(work, struct rhashtable, run_work); mutex_lock(&ht->mutex); + if (ht->being_destroyed) + goto unlock; + tbl = rht_dereference(ht->tbl, ht); list_for_each_entry(walker, &ht->walkers, list) @@ -499,6 +502,7 @@ static void rht_deferred_worker(struct work_struct *work) else if (ht->p.shrink_decision && ht->p.shrink_decision(ht, tbl->size)) rhashtable_shrink(ht); +unlock: mutex_unlock(&ht->mutex); }