From patchwork Mon Apr 27 02:28:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Lilijun (Jerry)" X-Patchwork-Id: 69355 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4A92EA00BE; Mon, 27 Apr 2020 04:28:44 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 84B6C1C0CD; Mon, 27 Apr 2020 04:28:43 +0200 (CEST) Received: from huawei.com (szxga01-in.huawei.com [45.249.212.187]) by dpdk.org (Postfix) with ESMTP id 3FDDC1C0BD; Mon, 27 Apr 2020 04:28:42 +0200 (CEST) Received: from dggeml406-hub.china.huawei.com (unknown [172.30.72.55]) by Forcepoint Email with ESMTP id ACF7F6CA618AD2A334BD; Mon, 27 Apr 2020 10:28:39 +0800 (CST) Received: from DGGEML529-MBX.china.huawei.com ([169.254.6.203]) by dggeml406-hub.china.huawei.com ([10.3.17.50]) with mapi id 14.03.0487.000; Mon, 27 Apr 2020 10:28:33 +0800 From: "Lilijun (Jerry)" To: "'dev@dpdk.org'" CC: wangyunjian , xudingke , "'stable@dpdk.org'" Thread-Topic: [dpdk-dev] [PATCH] lib/librte_hash: add rte_hash_del_key_fixed without compact Thread-Index: AdYcO135HJmvjYM1Q2CGkNRR8o1T1w== Date: Mon, 27 Apr 2020 02:28:33 +0000 Message-ID: <40280F65B1B0B44E8089ED31C01616EBA49921F2@dggeml529-mbx.china.huawei.com> Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.173.251.98] MIME-Version: 1.0 X-CFilter-Loop: Reflected Subject: [dpdk-dev] [PATCH] lib/librte_hash: add rte_hash_del_key_fixed without compact X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The keys idx are stored in rte_hash main bucket key slots and extend bucket key stots. We iterate every no empty Keys in h->buckets and h->buckets_ext from start to last. When deleting keys the function __rte_hash_compact_ll() may move last_bkt's key to previous bucket in order to compact extend bucket list. If the previous bucket has been iterated, the moved key may be missed for users. Then those missed keys are leaked and rte_hash table can't be cleanup. So we add a new API rte_hash_del_key_fixed() used in iterate loop to avoid this bugs. --- lib/librte_hash/rte_cuckoo_hash.c | 19 ++++++++++++++----- lib/librte_hash/rte_hash.h | 5 +++++ lib/librte_hash/rte_hash_version.map | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c index b52630b..2da3c1d 100644 --- a/lib/librte_hash/rte_cuckoo_hash.c +++ b/lib/librte_hash/rte_cuckoo_hash.c @@ -1523,7 +1523,7 @@ search_and_remove(const struct rte_hash *h, const void *key, static inline int32_t __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, - hash_sig_t sig) + hash_sig_t sig, uint8_t compact) { uint32_t prim_bucket_idx, sec_bucket_idx; struct rte_hash_bucket *prim_bkt, *sec_bkt, *prev_bkt, *last_bkt; @@ -1541,7 +1541,8 @@ __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, /* look for key in primary bucket */ ret = search_and_remove(h, key, prim_bkt, short_sig, &pos); if (ret != -1) { - __rte_hash_compact_ll(h, prim_bkt, pos); + if (compact) + __rte_hash_compact_ll(h, prim_bkt, pos); last_bkt = prim_bkt->next; prev_bkt = prim_bkt; goto return_bkt; @@ -1553,7 +1554,8 @@ __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, FOR_EACH_BUCKET(cur_bkt, sec_bkt) { ret = search_and_remove(h, key, cur_bkt, short_sig, &pos); if (ret != -1) { - __rte_hash_compact_ll(h, cur_bkt, pos); + if (compact) + __rte_hash_compact_ll(h, cur_bkt, pos); last_bkt = sec_bkt->next; prev_bkt = sec_bkt; goto return_bkt; @@ -1607,14 +1609,21 @@ rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t sig) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); - return __rte_hash_del_key_with_hash(h, key, sig); + return __rte_hash_del_key_with_hash(h, key, sig, 1); } int32_t rte_hash_del_key(const struct rte_hash *h, const void *key) { RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); - return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key)); + return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key), 1); +} + +int32_t +rte_hash_del_key_fixed(const struct rte_hash *h, const void *key) +{ + RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL); + return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key), 0); } int diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h index eceb365..9b71d8a 100644 --- a/lib/librte_hash/rte_hash.h +++ b/lib/librte_hash/rte_hash.h @@ -297,6 +297,11 @@ rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key, hash_sig_t int32_t rte_hash_del_key(const struct rte_hash *h, const void *key); + +/* for without compact */ +int32_t +rte_hash_del_key_fixed(const struct rte_hash *h, const void *key); + /** * Remove a key from an existing hash table. * This operation is not multi-thread safe diff --git a/lib/librte_hash/rte_hash_version.map b/lib/librte_hash/rte_hash_version.map index 30cc086..1941d17 100644 --- a/lib/librte_hash/rte_hash_version.map +++ b/lib/librte_hash/rte_hash_version.map @@ -11,6 +11,7 @@ DPDK_20.0 { rte_hash_count; rte_hash_create; rte_hash_del_key; + rte_hash_del_key_fixed; rte_hash_del_key_with_hash; rte_hash_find_existing; rte_hash_free;