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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).