Re: rhashtable: Fix potential crash on destroy in rhashtable_shrink
From: Ying Xue <hidden>
Date: 2015-02-02 09:35:28
On 01/31/2015 05:36 PM, Herbert Xu wrote:
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.
Sorry, I cannot understand the scenario. When we free the table in rhashtable_destroy(), we call cancel_work_sync() to synchronously cancel the work. So, why does your described crash still happen? Please give a more explanation. Thanks, Ying
quoted hunk ↗ jump to hunk
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 <herbert@gondor.apana.org.au>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); }