From: Thomas Graf <tgraf@suug.ch>
To: Ying Xue <ying.xue@windriver.com>
Cc: davem@davemloft.net, netdev@vger.kernel.org
Subject: Re: [PATCH net-next] rhashtable: involve rhashtable_lookup_insert routine
Date: Mon, 5 Jan 2015 09:46:35 +0000 [thread overview]
Message-ID: <20150105094635.GA31637@casper.infradead.org> (raw)
In-Reply-To: <54AA5465.5070102@windriver.com>
On 01/05/15 at 05:07pm, Ying Xue wrote:
> On 01/05/2015 04:46 PM, Ying Xue wrote:
> > Involve a new function called rhashtable_lookup_insert() which makes
> > lookup and insertion atomic under bucket lock protection, helping us
> > avoid to introduce an extra lock when we search and insert an object
> > into hash table.
> >
>
> Sorry, please ignore the version. We should compare key instead of
> object as we want to check whether in a bucket chain there is an entry
> whose key is identical with that of object to be inserted.
Agreed. Also, this needs to handle the special case while resizing is
taking place and tbl and future_tbl point to individual tables. In that
case a parallel writer might have or is about to add 'obj' to future_tbl.
We need something like this:
rcu_read_lock();
old_tbl = rht_dereference_rcu(ht->tbl, ht);
old_hash = head_hashfn(ht, old_tbl, obj);
old_bucket_lock = bucket_lock(old_tbl, old_hash);
spin_lock_bh(old_bucket_lock);
new_tbl = rht_dereference_rcu(ht->future_tbl, ht);
if (unlikely(old_tbl != new_tbl)) {
new_hash = head_hashfn(ht, new_tbl, obj);
new_bucket_lock = bucket_lock(new_tbl, new_hash);
spin_lock_bh_nested(new_bucket_lock, RHT_LOCK_NESTED1);
/* Resizing is in progress, search for a matching entry in the
* old table before attempting to insert to the future table.
*/
rht_for_each_rcu(he, tbl, rht_bucket_index(old_tbl, old_hash)) {
if (!memcmp(rht_obj(ht, he) + ht->p.key_offset,
rht_obj(ht, obj) + ht->p.key_offset,
ht->p.key_len))
goto entry_exists;
}
}
head = rht_dereference_bucket(new_tbl->buckets[hash], new_tbl, hash);
if (rht_is_a_nulls(head)) {
INIT_RHT_NULLS_HEAD(obj->next, ht, new_hash);
} else {
rht_for_each(he, new_tbl, new_hash) {
if (!memcmp(rht_obj(ht, he) + ht->p.key_offset,
rht_obj(ht, obj) + ht->p.key_offset,
ht->p.key_len))
goto entry_exists;
}
RCU_INIT_POINTER(obj->next, head);
}
rcu_assign_pointer(new_tbl->buckets[hash], obj);
spin_unlock_bh(new_bucket_lock);
if (unlikely(old_tbl != new_tbl))
spin_unlock_bh(old_bucket_lock);
atomic_inc(&ht->nelems);
/* Only grow the table if no resizing is currently in progress. */
if (ht->tbl != ht->future_tbl &&
ht->p.grow_decision && ht->p.grow_decision(ht, tbl->size))
schedule_delayed_work(&ht->run_work, 0);
rcu_read_unlock();
return true;
entry_exists:
spin_unlock_bh(new_bucket_lock);
spin_unlock_bh(old_bucket_lock);
rcu_read_unlock();
return false;
What this does in addition is:
* Locks down the bucket in both the old and new table if a resize is
in progress to ensure that writers can't remove from the old table
and can't insert to the new table during the atomic operation.
* Search for duplicates in the old table if a resize is in progress.
* Use memcmp() instead of ptr1 != ptr2 to search for duplicates
assuming we want to avoid key duplicates with this function.
*Please* verify this code very carefully, I wrote it out of my head
and did not compile or test it in any way yet. I'll double check and
think of a better unit test for this so we can validate functionality
like this.
next prev parent reply other threads:[~2015-01-05 9:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-05 8:46 [PATCH net-next] rhashtable: involve rhashtable_lookup_insert routine Ying Xue
2015-01-05 9:07 ` Ying Xue
2015-01-05 9:46 ` Thomas Graf [this message]
2015-01-05 11:44 ` Ying Xue
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150105094635.GA31637@casper.infradead.org \
--to=tgraf@suug.ch \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--cc=ying.xue@windriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.