From patchwork Tue Dec 2 11:16:26 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Pargmann X-Patchwork-Id: 4211 Return-Path: Received-SPF: None (no SPF record) identity=mailfrom; client-ip=92.198.50.35; helo=metis.ext.pengutronix.de; envelope-from=mpa@pengutronix.de; receiver=b.a.t.m.a.n@lists.open-mesh.org Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [92.198.50.35]) by open-mesh.org (Postfix) with ESMTPS id 0882260176A for ; Tue, 2 Dec 2014 12:41:03 +0100 (CET) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtp (Exim 4.72) (envelope-from ) id 1XvlYQ-0003LJ-NK; Tue, 02 Dec 2014 12:23:38 +0100 Received: from mpa by dude.hi.pengutronix.de with local (Exim 4.84) (envelope-from ) id 1XvlYP-0001YS-JA; Tue, 02 Dec 2014 12:23:37 +0100 From: Markus Pargmann To: Marek Lindner , Simon Wunderlich , Antonio Quartulli Date: Tue, 2 Dec 2014 12:16:26 +0100 Message-Id: <1417519009-20699-9-git-send-email-mpa@pengutronix.de> X-Mailer: git-send-email 2.1.3 In-Reply-To: <1417519009-20699-1-git-send-email-mpa@pengutronix.de> References: <1417519009-20699-1-git-send-email-mpa@pengutronix.de> X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: mpa@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: b.a.t.m.a.n@lists.open-mesh.org Cc: b.a.t.m.a.n@lists.open-mesh.org Subject: [B.A.T.M.A.N.] [PATCH 08/31] batman-adv: hash, remove function implementations from header X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Dec 2014 11:41:04 -0000 These functions are too big to be implemented as inline functions in the header file. This patch moves them to the hash c file. Signed-off-by: Markus Pargmann --- hash.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hash.h | 141 +++++------------------------------------------------------------ 2 files changed, 142 insertions(+), 131 deletions(-) diff --git a/hash.c b/hash.c index 7c1c63080e20..c68bb8b3e8b9 100644 --- a/hash.c +++ b/hash.c @@ -37,6 +37,35 @@ void batadv_hash_destroy(struct batadv_hashtable *hash) kfree(hash); } +/* remove the hash structure. if hashdata_free_cb != NULL, this function will be + * called to remove the elements inside of the hash. if you don't remove the + * elements, memory might be leaked. + */ +void batadv_hash_delete(struct batadv_hashtable *hash, + batadv_hashdata_free_cb free_cb, void *arg) +{ + struct hlist_head *head; + struct hlist_node *node, *node_tmp; + spinlock_t *list_lock; /* spinlock to protect write access */ + uint32_t i; + + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; + list_lock = &hash->list_locks[i]; + + spin_lock_bh(list_lock); + hlist_for_each_safe(node, node_tmp, head) { + hlist_del_rcu(node); + + if (free_cb) + free_cb(node, arg); + } + spin_unlock_bh(list_lock); + } + + batadv_hash_destroy(hash); +} + /* allocates and clears the hash */ struct batadv_hashtable *batadv_hash_new(uint32_t size) { @@ -74,3 +103,106 @@ void batadv_hash_set_lock_class(struct batadv_hashtable *hash, for (i = 0; i < hash->size; i++) lockdep_set_class(&hash->list_locks[i], key); } + +/** + * batadv_hash_bytes - hash some bytes and add them to the previous hash + * @hash: previous hash value + * @data: data to be hashed + * @size: number of bytes to be hashed + * + * Returns the new hash value. + */ +uint32_t batadv_hash_bytes(uint32_t hash, const void *data, uint32_t size) +{ + const unsigned char *key = data; + int i; + + for (i = 0; i < size; i++) { + hash += key[i]; + hash += (hash << 10); + hash ^= (hash >> 6); + } + + return hash; +} + +/** + * batadv_hash_add - adds data to the hashtable + * @hash: storage hash table + * @compare: callback to determine if 2 hash elements are identical + * @choose: callback calculating the hash index + * @data: data passed to the aforementioned callbacks as argument + * @data_node: to be added element + * + * Returns 0 on success, 1 if the element already is in the hash + * and -1 on error. + */ +int batadv_hash_add(struct batadv_hashtable *hash, + batadv_hashdata_compare_cb compare, + batadv_hashdata_choose_cb choose, const void *data, + struct hlist_node *data_node) +{ + uint32_t index; + int ret = -1; + struct hlist_head *head; + struct hlist_node *node; + spinlock_t *list_lock; /* spinlock to protect write access */ + + if (!hash) + goto out; + + index = choose(data, hash->size); + head = &hash->table[index]; + list_lock = &hash->list_locks[index]; + + spin_lock_bh(list_lock); + + hlist_for_each(node, head) { + if (!compare(node, data)) + continue; + + ret = 1; + goto unlock; + } + + /* no duplicate found in list, add new element */ + hlist_add_head_rcu(data_node, head); + + ret = 0; + +unlock: + spin_unlock_bh(list_lock); +out: + return ret; +} + +/* removes data from hash, if found. returns pointer do data on success, so you + * can remove the used structure yourself, or NULL on error . data could be the + * structure you use with just the key filled, we just need the key for + * comparing. + */ +void *batadv_hash_remove(struct batadv_hashtable *hash, + batadv_hashdata_compare_cb compare, + batadv_hashdata_choose_cb choose, void *data) +{ + uint32_t index; + struct hlist_node *node; + struct hlist_head *head; + void *data_save = NULL; + + index = choose(data, hash->size); + head = &hash->table[index]; + + spin_lock_bh(&hash->list_locks[index]); + hlist_for_each(node, head) { + if (!compare(node, data)) + continue; + + data_save = node; + hlist_del_rcu(node); + break; + } + spin_unlock_bh(&hash->list_locks[index]); + + return data_save; +} diff --git a/hash.h b/hash.h index 539fc1266793..0761b64be337 100644 --- a/hash.h +++ b/hash.h @@ -49,139 +49,18 @@ void batadv_hash_set_lock_class(struct batadv_hashtable *hash, /* free only the hashtable and the hash itself. */ void batadv_hash_destroy(struct batadv_hashtable *hash); -/* remove the hash structure. if hashdata_free_cb != NULL, this function will be - * called to remove the elements inside of the hash. if you don't remove the - * elements, memory might be leaked. - */ -static inline void batadv_hash_delete(struct batadv_hashtable *hash, - batadv_hashdata_free_cb free_cb, - void *arg) -{ - struct hlist_head *head; - struct hlist_node *node, *node_tmp; - spinlock_t *list_lock; /* spinlock to protect write access */ - uint32_t i; - - for (i = 0; i < hash->size; i++) { - head = &hash->table[i]; - list_lock = &hash->list_locks[i]; - - spin_lock_bh(list_lock); - hlist_for_each_safe(node, node_tmp, head) { - hlist_del_rcu(node); - - if (free_cb) - free_cb(node, arg); - } - spin_unlock_bh(list_lock); - } - - batadv_hash_destroy(hash); -} - -/** - * batadv_hash_bytes - hash some bytes and add them to the previous hash - * @hash: previous hash value - * @data: data to be hashed - * @size: number of bytes to be hashed - * - * Returns the new hash value. - */ -static inline uint32_t batadv_hash_bytes(uint32_t hash, const void *data, - uint32_t size) -{ - const unsigned char *key = data; - int i; - - for (i = 0; i < size; i++) { - hash += key[i]; - hash += (hash << 10); - hash ^= (hash >> 6); - } - return hash; -} - -/** - * batadv_hash_add - adds data to the hashtable - * @hash: storage hash table - * @compare: callback to determine if 2 hash elements are identical - * @choose: callback calculating the hash index - * @data: data passed to the aforementioned callbacks as argument - * @data_node: to be added element - * - * Returns 0 on success, 1 if the element already is in the hash - * and -1 on error. - */ -static inline int batadv_hash_add(struct batadv_hashtable *hash, - batadv_hashdata_compare_cb compare, - batadv_hashdata_choose_cb choose, - const void *data, - struct hlist_node *data_node) -{ - uint32_t index; - int ret = -1; - struct hlist_head *head; - struct hlist_node *node; - spinlock_t *list_lock; /* spinlock to protect write access */ - - if (!hash) - goto out; - - index = choose(data, hash->size); - head = &hash->table[index]; - list_lock = &hash->list_locks[index]; - - spin_lock_bh(list_lock); - - hlist_for_each(node, head) { - if (!compare(node, data)) - continue; - - ret = 1; - goto unlock; - } - - /* no duplicate found in list, add new element */ - hlist_add_head_rcu(data_node, head); - - ret = 0; - -unlock: - spin_unlock_bh(list_lock); -out: - return ret; -} - -/* removes data from hash, if found. returns pointer do data on success, so you - * can remove the used structure yourself, or NULL on error . data could be the - * structure you use with just the key filled, we just need the key for - * comparing. - */ -static inline void *batadv_hash_remove(struct batadv_hashtable *hash, - batadv_hashdata_compare_cb compare, - batadv_hashdata_choose_cb choose, - void *data) -{ - uint32_t index; - struct hlist_node *node; - struct hlist_head *head; - void *data_save = NULL; - - index = choose(data, hash->size); - head = &hash->table[index]; +uint32_t batadv_hash_bytes(uint32_t hash, const void *data, uint32_t size); - spin_lock_bh(&hash->list_locks[index]); - hlist_for_each(node, head) { - if (!compare(node, data)) - continue; +int batadv_hash_add(struct batadv_hashtable *hash, + batadv_hashdata_compare_cb compare, + batadv_hashdata_choose_cb choose, const void *data, + struct hlist_node *data_node); - data_save = node; - hlist_del_rcu(node); - break; - } - spin_unlock_bh(&hash->list_locks[index]); +void batadv_hash_delete(struct batadv_hashtable *hash, + batadv_hashdata_free_cb free_cb, void *arg); - return data_save; -} +void *batadv_hash_remove(struct batadv_hashtable *hash, + batadv_hashdata_compare_cb compare, + batadv_hashdata_choose_cb choose, void *data); #endif /* _NET_BATMAN_ADV_HASH_H_ */