Commit bd204952 authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Greg Kroah-Hartman

Staging: batman-adv: Rewrite hash using hlist_*

The hash implementation is a complete implementation of a hash using
buckets as hash entries and overflow buckets attached to them.

The kernel already provides datastructures hlist_head and hlist_node
which can be used to implement an hash using lists as hash buckets. So
it is better to implement heavily used functionality on top of those
instead of providing a full hash implementation.

The rewrite changes the behavior of some functions slightly:
 * hash_add add elements to the front instead of the tail
 * hash_iterate doesn't provide pointer to access bucket->data directly,
   but it can be accessed using hlist_entry
Reported-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent a3238c3b
* remove own list functionality from hash
* use hlist_head, hlist_node in hash
* Request a new review * Request a new review
* Process the comments from the review * Process the comments from the review
* Move into mainline proper * Move into mainline proper
......
...@@ -30,7 +30,7 @@ static void hash_init(struct hashtable_t *hash) ...@@ -30,7 +30,7 @@ static void hash_init(struct hashtable_t *hash)
hash->elements = 0; hash->elements = 0;
for (i = 0 ; i < hash->size; i++) for (i = 0 ; i < hash->size; i++)
hash->table[i] = NULL; INIT_HLIST_HEAD(&hash->table[i]);
} }
/* free only the hashtable and the hash itself. */ /* free only the hashtable and the hash itself. */
...@@ -70,15 +70,13 @@ struct hashtable_t *hash_new(int size) ...@@ -70,15 +70,13 @@ struct hashtable_t *hash_new(int size)
void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t) void *hash_remove_bucket(struct hashtable_t *hash, struct hash_it_t *hash_it_t)
{ {
void *data_save; void *data_save;
struct element_t *bucket;
data_save = hash_it_t->bucket->data; bucket = hlist_entry(hash_it_t->walk, struct element_t, hlist);
data_save = bucket->data;
if (hash_it_t->prev_bucket != NULL) hlist_del(hash_it_t->walk);
hash_it_t->prev_bucket->next = hash_it_t->bucket->next; kfree(bucket);
else if (hash_it_t->first_bucket != NULL)
(*hash_it_t->first_bucket) = hash_it_t->bucket->next;
kfree(hash_it_t->bucket);
hash->elements--; hash->elements--;
return data_save; return data_save;
......
...@@ -22,10 +22,11 @@ ...@@ -22,10 +22,11 @@
#ifndef _NET_BATMAN_ADV_HASH_H_ #ifndef _NET_BATMAN_ADV_HASH_H_
#define _NET_BATMAN_ADV_HASH_H_ #define _NET_BATMAN_ADV_HASH_H_
#include <linux/list.h>
#define HASHIT(name) struct hash_it_t name = { \ #define HASHIT(name) struct hash_it_t name = { \
.index = -1, .bucket = NULL, \ .index = 0, .walk = NULL, \
.prev_bucket = NULL, \ .safe = NULL}
.first_bucket = NULL }
/* callback to a compare function. should /* callback to a compare function. should
* compare 2 element datas for their keys, * compare 2 element datas for their keys,
...@@ -41,18 +42,17 @@ typedef void (*hashdata_free_cb)(void *, void *); ...@@ -41,18 +42,17 @@ typedef void (*hashdata_free_cb)(void *, void *);
struct element_t { struct element_t {
void *data; /* pointer to the data */ void *data; /* pointer to the data */
struct element_t *next; /* overflow bucket pointer */ struct hlist_node hlist; /* bucket list pointer */
}; };
struct hash_it_t { struct hash_it_t {
int index; size_t index;
struct element_t *bucket; struct hlist_node *walk;
struct element_t *prev_bucket; struct hlist_node *safe;
struct element_t **first_bucket;
}; };
struct hashtable_t { struct hashtable_t {
struct element_t **table; /* the hashtable itself, with the buckets */ struct hlist_head *table; /* the hashtable itself, with the buckets */
int elements; /* number of elements registered */ int elements; /* number of elements registered */
int size; /* size of hashtable */ int size; /* size of hashtable */
}; };
...@@ -75,19 +75,21 @@ void hash_destroy(struct hashtable_t *hash); ...@@ -75,19 +75,21 @@ void hash_destroy(struct hashtable_t *hash);
static inline void hash_delete(struct hashtable_t *hash, static inline void hash_delete(struct hashtable_t *hash,
hashdata_free_cb free_cb, void *arg) hashdata_free_cb free_cb, void *arg)
{ {
struct element_t *bucket, *last_bucket; struct hlist_head *head;
struct hlist_node *walk, *safe;
struct element_t *bucket;
int i; int i;
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
bucket = hash->table[i]; head = &hash->table[i];
while (bucket != NULL) { hlist_for_each_safe(walk, safe, head) {
bucket = hlist_entry(walk, struct element_t, hlist);
if (free_cb != NULL) if (free_cb != NULL)
free_cb(bucket->data, arg); free_cb(bucket->data, arg);
last_bucket = bucket; hlist_del(walk);
bucket = bucket->next; kfree(bucket);
kfree(last_bucket);
} }
} }
...@@ -100,36 +102,30 @@ static inline int hash_add(struct hashtable_t *hash, ...@@ -100,36 +102,30 @@ static inline int hash_add(struct hashtable_t *hash,
hashdata_choose_cb choose, void *data) hashdata_choose_cb choose, void *data)
{ {
int index; int index;
struct element_t *bucket, *prev_bucket = NULL; struct hlist_head *head;
struct hlist_node *walk, *safe;
struct element_t *bucket;
if (!hash) if (!hash)
return -1; return -1;
index = choose(data, hash->size); index = choose(data, hash->size);
bucket = hash->table[index]; head = &hash->table[index];
while (bucket != NULL) { hlist_for_each_safe(walk, safe, head) {
bucket = hlist_entry(walk, struct element_t, hlist);
if (compare(bucket->data, data)) if (compare(bucket->data, data))
return -1; return -1;
prev_bucket = bucket;
bucket = bucket->next;
} }
/* found the tail of the list, add new element */ /* no duplicate found in list, add new element */
bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC); bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC);
if (bucket == NULL) if (bucket == NULL)
return -1; return -1;
bucket->data = data; bucket->data = data;
bucket->next = NULL; hlist_add_head(&bucket->hlist, head);
/* and link it */
if (prev_bucket == NULL)
hash->table[index] = bucket;
else
prev_bucket->next = bucket;
hash->elements++; hash->elements++;
return 0; return 0;
...@@ -144,22 +140,16 @@ static inline void *hash_remove(struct hashtable_t *hash, ...@@ -144,22 +140,16 @@ static inline void *hash_remove(struct hashtable_t *hash,
hashdata_choose_cb choose, void *data) hashdata_choose_cb choose, void *data)
{ {
struct hash_it_t hash_it_t; struct hash_it_t hash_it_t;
struct element_t *bucket;
struct hlist_head *head;
hash_it_t.index = choose(data, hash->size); hash_it_t.index = choose(data, hash->size);
hash_it_t.bucket = hash->table[hash_it_t.index]; head = &hash->table[hash_it_t.index];
hash_it_t.prev_bucket = NULL;
while (hash_it_t.bucket != NULL) {
if (compare(hash_it_t.bucket->data, data)) {
hash_it_t.first_bucket =
(hash_it_t.bucket ==
hash->table[hash_it_t.index] ?
&hash->table[hash_it_t.index] : NULL);
return hash_remove_bucket(hash, &hash_it_t);
}
hash_it_t.prev_bucket = hash_it_t.bucket; hlist_for_each(hash_it_t.walk, head) {
hash_it_t.bucket = hash_it_t.bucket->next; bucket = hlist_entry(hash_it_t.walk, struct element_t, hlist);
if (compare(bucket->data, data))
return hash_remove_bucket(hash, &hash_it_t);
} }
return NULL; return NULL;
...@@ -172,19 +162,20 @@ static inline void *hash_find(struct hashtable_t *hash, ...@@ -172,19 +162,20 @@ static inline void *hash_find(struct hashtable_t *hash,
hashdata_choose_cb choose, void *keydata) hashdata_choose_cb choose, void *keydata)
{ {
int index; int index;
struct hlist_head *head;
struct hlist_node *walk;
struct element_t *bucket; struct element_t *bucket;
if (!hash) if (!hash)
return NULL; return NULL;
index = choose(keydata , hash->size); index = choose(keydata , hash->size);
bucket = hash->table[index]; head = &hash->table[index];
while (bucket != NULL) { hlist_for_each(walk, head) {
bucket = hlist_entry(walk, struct element_t, hlist);
if (compare(bucket->data, keydata)) if (compare(bucket->data, keydata))
return bucket->data; return bucket->data;
bucket = bucket->next;
} }
return NULL; return NULL;
...@@ -193,13 +184,14 @@ static inline void *hash_find(struct hashtable_t *hash, ...@@ -193,13 +184,14 @@ static inline void *hash_find(struct hashtable_t *hash,
/* resize the hash, returns the pointer to the new hash or NULL on /* resize the hash, returns the pointer to the new hash or NULL on
* error. removes the old hash on success */ * error. removes the old hash on success */
static inline struct hashtable_t *hash_resize(struct hashtable_t *hash, static inline struct hashtable_t *hash_resize(struct hashtable_t *hash,
hashdata_compare_cb compare,
hashdata_choose_cb choose, hashdata_choose_cb choose,
int size) int size)
{ {
struct hashtable_t *new_hash; struct hashtable_t *new_hash;
struct hlist_head *head, *new_head;
struct hlist_node *walk, *safe;
struct element_t *bucket; struct element_t *bucket;
int i; int i, new_index;
/* initialize a new hash with the new size */ /* initialize a new hash with the new size */
new_hash = hash_new(size); new_hash = hash_new(size);
...@@ -209,17 +201,20 @@ static inline struct hashtable_t *hash_resize(struct hashtable_t *hash, ...@@ -209,17 +201,20 @@ static inline struct hashtable_t *hash_resize(struct hashtable_t *hash,
/* copy the elements */ /* copy the elements */
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
bucket = hash->table[i]; head = &hash->table[i];
hlist_for_each_safe(walk, safe, head) {
bucket = hlist_entry(walk, struct element_t, hlist);
while (bucket != NULL) { new_index = choose(bucket->data, size);
hash_add(new_hash, compare, choose, bucket->data); new_head = &new_hash->table[new_index];
bucket = bucket->next;
hlist_del(walk);
hlist_add_head(walk, new_head);
} }
} }
/* remove hash and eventual overflow buckets but not the content hash_destroy(hash);
* itself. */
hash_delete(hash, NULL, NULL);
return new_hash; return new_hash;
} }
...@@ -236,63 +231,29 @@ static inline struct hash_it_t *hash_iterate(struct hashtable_t *hash, ...@@ -236,63 +231,29 @@ static inline struct hash_it_t *hash_iterate(struct hashtable_t *hash,
if (!iter) if (!iter)
return NULL; return NULL;
/* sanity checks first (if our bucket got deleted in the last iter->walk = iter->safe;
* iteration): */
if (iter->bucket != NULL) {
if (iter->first_bucket != NULL) {
/* we're on the first element and it got removed after
* the last iteration. */
if ((*iter->first_bucket) != iter->bucket) {
/* there are still other elements in the list */
if ((*iter->first_bucket) != NULL) {
iter->prev_bucket = NULL;
iter->bucket = (*iter->first_bucket);
iter->first_bucket =
&hash->table[iter->index];
return iter;
} else {
iter->bucket = NULL;
}
}
} else if (iter->prev_bucket != NULL) {
/*
* we're not on the first element, and the bucket got
* removed after the last iteration. the last bucket's
* next pointer is not pointing to our actual bucket
* anymore. select the next.
*/
if (iter->prev_bucket->next != iter->bucket)
iter->bucket = iter->prev_bucket;
}
}
/* now as we are sane, select the next one if there is some */ /* we search for the next head with list entries */
if (iter->bucket != NULL) { if (!iter->walk) {
if (iter->bucket->next != NULL) { while (iter->index < hash->size) {
iter->prev_bucket = iter->bucket; if (hlist_empty(&hash->table[iter->index]))
iter->bucket = iter->bucket->next; iter->index++;
iter->first_bucket = NULL; else {
return iter; iter->walk = hash->table[iter->index].first;
}
}
/* if not returned yet, we've reached the last one on the index and have /* search next time */
* to search forward */ ++iter->index;
iter->index++; break;
/* go through the entries of the hash table */ }
while (iter->index < hash->size) {
if ((hash->table[iter->index]) != NULL) {
iter->prev_bucket = NULL;
iter->bucket = hash->table[iter->index];
iter->first_bucket = &hash->table[iter->index];
return iter;
} else {
iter->index++;
} }
} }
/* nothing to iterate over anymore */ /* return iter when we found bucket otherwise null */
return NULL; if (!iter->walk)
return NULL;
iter->safe = iter->walk->next;
return iter;
} }
#endif /* _NET_BATMAN_ADV_HASH_H_ */ #endif /* _NET_BATMAN_ADV_HASH_H_ */
...@@ -175,8 +175,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) ...@@ -175,8 +175,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
goto free_bcast_own_sum; goto free_bcast_own_sum;
if (bat_priv->orig_hash->elements * 4 > bat_priv->orig_hash->size) { if (bat_priv->orig_hash->elements * 4 > bat_priv->orig_hash->size) {
swaphash = hash_resize(bat_priv->orig_hash, compare_orig, swaphash = hash_resize(bat_priv->orig_hash, choose_orig,
choose_orig,
bat_priv->orig_hash->size * 2); bat_priv->orig_hash->size * 2);
if (!swaphash) if (!swaphash)
...@@ -272,6 +271,7 @@ static bool purge_orig_node(struct bat_priv *bat_priv, ...@@ -272,6 +271,7 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
static void _purge_orig(struct bat_priv *bat_priv) static void _purge_orig(struct bat_priv *bat_priv)
{ {
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
struct orig_node *orig_node; struct orig_node *orig_node;
unsigned long flags; unsigned long flags;
...@@ -279,7 +279,8 @@ static void _purge_orig(struct bat_priv *bat_priv) ...@@ -279,7 +279,8 @@ static void _purge_orig(struct bat_priv *bat_priv)
/* for all origins... */ /* for all origins... */
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = bucket->data;
if (purge_orig_node(bat_priv, orig_node)) { if (purge_orig_node(bat_priv, orig_node)) {
hash_remove_bucket(bat_priv->orig_hash, &hashit); hash_remove_bucket(bat_priv->orig_hash, &hashit);
...@@ -315,6 +316,7 @@ void purge_orig_ref(struct bat_priv *bat_priv) ...@@ -315,6 +316,7 @@ void purge_orig_ref(struct bat_priv *bat_priv)
int orig_seq_print_text(struct seq_file *seq, void *offset) int orig_seq_print_text(struct seq_file *seq, void *offset)
{ {
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
struct net_device *net_dev = (struct net_device *)seq->private; struct net_device *net_dev = (struct net_device *)seq->private;
struct bat_priv *bat_priv = netdev_priv(net_dev); struct bat_priv *bat_priv = netdev_priv(net_dev);
struct orig_node *orig_node; struct orig_node *orig_node;
...@@ -347,8 +349,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) ...@@ -347,8 +349,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = hashit.bucket->data; orig_node = bucket->data;
if (!orig_node->router) if (!orig_node->router)
continue; continue;
...@@ -419,13 +421,15 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) ...@@ -419,13 +421,15 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
struct orig_node *orig_node; struct orig_node *orig_node;
unsigned long flags; unsigned long flags;
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */ * if_num */
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = bucket->data;
if (orig_node_add_if(orig_node, max_if_num) == -1) if (orig_node_add_if(orig_node, max_if_num) == -1)
goto err; goto err;
...@@ -498,6 +502,7 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) ...@@ -498,6 +502,7 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
struct orig_node *orig_node; struct orig_node *orig_node;
unsigned long flags; unsigned long flags;
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
int ret; int ret;
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on /* resize all orig nodes because orig_node->bcast_own(_sum) depend on
...@@ -505,7 +510,8 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) ...@@ -505,7 +510,8 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = bucket->data;
ret = orig_node_del_if(orig_node, max_if_num, ret = orig_node_del_if(orig_node, max_if_num,
batman_if->if_num); batman_if->if_num);
......
...@@ -38,6 +38,7 @@ void slide_own_bcast_window(struct batman_if *batman_if) ...@@ -38,6 +38,7 @@ void slide_own_bcast_window(struct batman_if *batman_if)
{ {
struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
struct orig_node *orig_node; struct orig_node *orig_node;
TYPE_OF_WORD *word; TYPE_OF_WORD *word;
unsigned long flags; unsigned long flags;
...@@ -45,7 +46,8 @@ void slide_own_bcast_window(struct batman_if *batman_if) ...@@ -45,7 +46,8 @@ void slide_own_bcast_window(struct batman_if *batman_if)
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = bucket->data;
word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]); word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
bit_get_packet(bat_priv, word, 1, 0); bit_get_packet(bat_priv, word, 1, 0);
......
...@@ -116,8 +116,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr) ...@@ -116,8 +116,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
if (bat_priv->hna_local_hash->elements * 4 > if (bat_priv->hna_local_hash->elements * 4 >
bat_priv->hna_local_hash->size) { bat_priv->hna_local_hash->size) {
swaphash = hash_resize(bat_priv->hna_local_hash, compare_orig, swaphash = hash_resize(bat_priv->hna_local_hash, choose_orig,
choose_orig,
bat_priv->hna_local_hash->size * 2); bat_priv->hna_local_hash->size * 2);
if (!swaphash) if (!swaphash)
...@@ -146,6 +145,7 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv, ...@@ -146,6 +145,7 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv,
unsigned char *buff, int buff_len) unsigned char *buff, int buff_len)
{ {
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
struct element_t *bucket;
HASHIT(hashit); HASHIT(hashit);
int i = 0; int i = 0;
unsigned long flags; unsigned long flags;
...@@ -157,7 +157,8 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv, ...@@ -157,7 +157,8 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv,
if (buff_len < (i + 1) * ETH_ALEN) if (buff_len < (i + 1) * ETH_ALEN)
break; break;
hna_local_entry = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
hna_local_entry = bucket->data;
memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN); memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
i++; i++;
...@@ -178,6 +179,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -178,6 +179,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
HASHIT(hashit); HASHIT(hashit);
HASHIT(hashit_count); HASHIT(hashit_count);
struct element_t *bucket;
unsigned long flags; unsigned long flags;
size_t buf_size, pos; size_t buf_size, pos;
char *buff; char *buff;
...@@ -208,7 +210,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -208,7 +210,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
pos = 0; pos = 0;
while (hash_iterate(bat_priv->hna_local_hash, &hashit)) { while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
hna_local_entry = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
hna_local_entry = bucket->data;
pos += snprintf(buff + pos, 22, " * %pM\n", pos += snprintf(buff + pos, 22, " * %pM\n",
hna_local_entry->addr); hna_local_entry->addr);
...@@ -267,13 +270,15 @@ static void hna_local_purge(struct work_struct *work) ...@@ -267,13 +270,15 @@ static void hna_local_purge(struct work_struct *work)
container_of(delayed_work, struct bat_priv, hna_work); container_of(delayed_work, struct bat_priv, hna_work);
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
unsigned long flags; unsigned long flags;
unsigned long timeout; unsigned long timeout;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags); spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
while (hash_iterate(bat_priv->hna_local_hash, &hashit)) { while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
hna_local_entry = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
hna_local_entry = bucket->data;
timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ; timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;
...@@ -389,8 +394,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv, ...@@ -389,8 +394,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
if (bat_priv->hna_global_hash->elements * 4 > if (bat_priv->hna_global_hash->elements * 4 >
bat_priv->hna_global_hash->size) { bat_priv->hna_global_hash->size) {
swaphash = hash_resize(bat_priv->hna_global_hash, compare_orig, swaphash = hash_resize(bat_priv->hna_global_hash, choose_orig,
choose_orig,
bat_priv->hna_global_hash->size * 2); bat_priv->hna_global_hash->size * 2);
if (!swaphash) if (!swaphash)
...@@ -409,6 +413,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) ...@@ -409,6 +413,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
struct hna_global_entry *hna_global_entry; struct hna_global_entry *hna_global_entry;
HASHIT(hashit); HASHIT(hashit);
HASHIT(hashit_count); HASHIT(hashit_count);
struct element_t *bucket;
unsigned long flags; unsigned long flags;
size_t buf_size, pos; size_t buf_size, pos;
char *buff; char *buff;
...@@ -438,7 +443,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) ...@@ -438,7 +443,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
pos = 0; pos = 0;
while (hash_iterate(bat_priv->hna_global_hash, &hashit)) { while (hash_iterate(bat_priv->hna_global_hash, &hashit)) {
hna_global_entry = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
hna_global_entry = bucket->data;
pos += snprintf(buff + pos, 44, pos += snprintf(buff + pos, 44,
" * %pM via %pM\n", hna_global_entry->addr, " * %pM via %pM\n", hna_global_entry->addr,
......
...@@ -177,6 +177,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) ...@@ -177,6 +177,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
{ {
HASHIT(hashit); HASHIT(hashit);
HASHIT(hashit_count); HASHIT(hashit_count);
struct element_t *bucket;
struct vis_info *info; struct vis_info *info;
struct vis_packet *packet; struct vis_packet *packet;
struct vis_info_entry *entries; struct vis_info_entry *entries;
...@@ -199,7 +200,9 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) ...@@ -199,7 +200,9 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
/* Estimate length */ /* Estimate length */
spin_lock_irqsave(&bat_priv->vis_hash_lock, flags); spin_lock_irqsave(&bat_priv->vis_hash_lock, flags);
while (hash_iterate(bat_priv->vis_hash, &hashit_count)) { while (hash_iterate(bat_priv->vis_hash, &hashit_count)) {
info = hashit_count.bucket->data; bucket = hlist_entry(hashit_count.walk, struct element_t,
hlist);
info = bucket->data;
packet = (struct vis_packet *)info->skb_packet->data; packet = (struct vis_packet *)info->skb_packet->data;
entries = (struct vis_info_entry *) entries = (struct vis_info_entry *)
((char *)packet + sizeof(struct vis_packet)); ((char *)packet + sizeof(struct vis_packet));
...@@ -237,7 +240,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) ...@@ -237,7 +240,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
buff_pos = 0; buff_pos = 0;
while (hash_iterate(bat_priv->vis_hash, &hashit)) { while (hash_iterate(bat_priv->vis_hash, &hashit)) {
info = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
info = bucket->data;
packet = (struct vis_packet *)info->skb_packet->data; packet = (struct vis_packet *)info->skb_packet->data;
entries = (struct vis_info_entry *) entries = (struct vis_info_entry *)
((char *)packet + sizeof(struct vis_packet)); ((char *)packet + sizeof(struct vis_packet));
...@@ -515,6 +519,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv, ...@@ -515,6 +519,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
struct vis_info *info) struct vis_info *info)
{ {
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
struct orig_node *orig_node; struct orig_node *orig_node;
struct vis_packet *packet; struct vis_packet *packet;
int best_tq = -1; int best_tq = -1;
...@@ -522,7 +527,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv, ...@@ -522,7 +527,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
packet = (struct vis_packet *)info->skb_packet->data; packet = (struct vis_packet *)info->skb_packet->data;
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = bucket->data;
if ((orig_node) && (orig_node->router) && if ((orig_node) && (orig_node->router) &&
(orig_node->flags & VIS_SERVER) && (orig_node->flags & VIS_SERVER) &&
(orig_node->router->tq_avg > best_tq)) { (orig_node->router->tq_avg > best_tq)) {
...@@ -551,6 +557,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) ...@@ -551,6 +557,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
{ {
HASHIT(hashit_local); HASHIT(hashit_local);
HASHIT(hashit_global); HASHIT(hashit_global);
struct element_t *bucket;
struct orig_node *orig_node; struct orig_node *orig_node;
struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data;
...@@ -580,7 +587,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv) ...@@ -580,7 +587,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
} }
while (hash_iterate(bat_priv->orig_hash, &hashit_global)) { while (hash_iterate(bat_priv->orig_hash, &hashit_global)) {
orig_node = hashit_global.bucket->data; bucket = hlist_entry(hashit_global.walk, struct element_t,
hlist);
orig_node = bucket->data;
if (!orig_node->router) if (!orig_node->router)
continue; continue;
...@@ -615,7 +624,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv) ...@@ -615,7 +624,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags); spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
while (hash_iterate(bat_priv->hna_local_hash, &hashit_local)) { while (hash_iterate(bat_priv->hna_local_hash, &hashit_local)) {
hna_local_entry = hashit_local.bucket->data; bucket = hlist_entry(hashit_local.walk, struct element_t,
hlist);
hna_local_entry = bucket->data;
entry = (struct vis_info_entry *)skb_put(info->skb_packet, entry = (struct vis_info_entry *)skb_put(info->skb_packet,
sizeof(*entry)); sizeof(*entry));
memset(entry->src, 0, ETH_ALEN); memset(entry->src, 0, ETH_ALEN);
...@@ -639,10 +650,12 @@ static int generate_vis_packet(struct bat_priv *bat_priv) ...@@ -639,10 +650,12 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
static void purge_vis_packets(struct bat_priv *bat_priv) static void purge_vis_packets(struct bat_priv *bat_priv)
{ {
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
struct vis_info *info; struct vis_info *info;
while (hash_iterate(bat_priv->vis_hash, &hashit)) { while (hash_iterate(bat_priv->vis_hash, &hashit)) {
info = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
info = bucket->data;
/* never purge own data. */ /* never purge own data. */
if (info == bat_priv->my_vis_info) if (info == bat_priv->my_vis_info)
...@@ -661,6 +674,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, ...@@ -661,6 +674,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
struct vis_info *info) struct vis_info *info)
{ {
HASHIT(hashit); HASHIT(hashit);
struct element_t *bucket;
struct orig_node *orig_node; struct orig_node *orig_node;
struct vis_packet *packet; struct vis_packet *packet;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -674,7 +688,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, ...@@ -674,7 +688,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
/* send to all routers in range. */ /* send to all routers in range. */
while (hash_iterate(bat_priv->orig_hash, &hashit)) { while (hash_iterate(bat_priv->orig_hash, &hashit)) {
orig_node = hashit.bucket->data; bucket = hlist_entry(hashit.walk, struct element_t, hlist);
orig_node = bucket->data;
/* if it's a vis server and reachable, send it. */ /* if it's a vis server and reachable, send it. */
if ((!orig_node) || (!orig_node->router)) if ((!orig_node) || (!orig_node->router))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment