From 2e79c44597547799d9501940b660f676a559b738 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 21 Dec 2011 08:53:48 -0500 Subject: [PATCH] cds_lfht_replace: add checks for old/new node hash/value match Also initialize reverse hash in replace. Signed-off-by: Mathieu Desnoyers --- rculfhash.c | 13 ++++++++++++- urcu/rculfhash.h | 17 +++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/rculfhash.c b/rculfhash.c index 75e5ece..1eda2dd 100644 --- a/rculfhash.c +++ b/rculfhash.c @@ -1517,11 +1517,22 @@ struct cds_lfht_node *cds_lfht_add_replace(struct cds_lfht *ht, } } -int cds_lfht_replace(struct cds_lfht *ht, struct cds_lfht_iter *old_iter, +int cds_lfht_replace(struct cds_lfht *ht, + struct cds_lfht_iter *old_iter, + unsigned long hash, + cds_lfht_match_fct match, + const void *key, struct cds_lfht_node *new_node) { unsigned long size; + new_node->reverse_hash = bit_reverse_ulong((unsigned long) hash); + if (!old_iter->node) + return -ENOENT; + if (caa_unlikely(old_iter->node->reverse_hash != new_node->reverse_hash)) + return -EINVAL; + if (caa_unlikely(!match(old_iter->node, key))) + return -EINVAL; size = rcu_dereference(ht->size); return _cds_lfht_replace(ht, size, old_iter->node, old_iter->next, new_node); diff --git a/urcu/rculfhash.h b/urcu/rculfhash.h index b33ede0..96dc5a0 100644 --- a/urcu/rculfhash.h +++ b/urcu/rculfhash.h @@ -325,11 +325,16 @@ struct cds_lfht_node *cds_lfht_add_replace(struct cds_lfht *ht, * cds_lfht_replace - replace a node pointer to by iter within hash table. * @ht: the hash table. * @old_iter: the iterator position of the node to replace. - * @now_node: the new node to try using for replacement. + * @hash: the node's hash. + * @match: the key match function. + * @key: the node's key. + * @new_node: the new node to use as replacement. * * Return 0 if replacement is successful, negative value otherwise. - * Replacing a NULL old node or an already removed node will fail with a - * negative value. + * Replacing a NULL old node or an already removed node will fail with + * -ENOENT. + * If the hash or value of the node to replace and the new node differ, + * this function returns -EINVAL without proceeding to the replacement. * Old node can be looked up with cds_lfht_lookup and cds_lfht_next. * RCU read-side lock must be held between lookup and replacement. * Call with rcu_read_lock held. @@ -348,7 +353,11 @@ struct cds_lfht_node *cds_lfht_add_replace(struct cds_lfht *ht, * guarantee that a combination of add_replace and add_unique updates * will never generate duplicated keys. */ -int cds_lfht_replace(struct cds_lfht *ht, struct cds_lfht_iter *old_iter, +int cds_lfht_replace(struct cds_lfht *ht, + struct cds_lfht_iter *old_iter, + unsigned long hash, + cds_lfht_match_fct match, + const void *key, struct cds_lfht_node *new_node); /* -- 2.34.1