To avoid a race condition while creating a new hash object, the
list has to be locked before the lookup, and released only once the
new object is added in the list.

Signed-off-by: Olivier Matz <olivier.matz at 6wind.com>
---
 lib/librte_hash/rte_cuckoo_hash.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib/librte_hash/rte_cuckoo_hash.c 
b/lib/librte_hash/rte_cuckoo_hash.c
index ccec2db..18351fa 100644
--- a/lib/librte_hash/rte_cuckoo_hash.c
+++ b/lib/librte_hash/rte_cuckoo_hash.c
@@ -228,11 +228,17 @@ rte_hash_create(const struct rte_hash_parameters *params)

        snprintf(hash_name, sizeof(hash_name), "HT_%s", params->name);

-       /* Guarantee there's no existing */
-       h = rte_hash_find_existing(params->name);
-       if (h != NULL) {
+       rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+       /* guarantee there's no existing */
+       TAILQ_FOREACH(te, hash_list, next) {
+               h = (struct rte_hash *) te->data;
+               if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0)
+                       break;
+       }
+       if (te != NULL) {
                rte_errno = EEXIST;
-               return NULL;
+               goto err;
        }

        te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0);
@@ -359,13 +365,13 @@ rte_hash_create(const struct rte_hash_parameters *params)
        for (i = 1; i < params->entries + 1; i++)
                rte_ring_sp_enqueue(r, (void *)((uintptr_t) i));

-       rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
        te->data = (void *) h;
        TAILQ_INSERT_TAIL(hash_list, te, next);
        rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);

        return h;
 err:
+       rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
        rte_free(te);
        rte_free(h);
        rte_free(buckets);
-- 
2.1.4

Reply via email to