Skip to content

Commit

Permalink
Staging: batman-adv: initialize static hash iterators
Browse files Browse the repository at this point in the history
instead of dynamically registering hash iterators, calling functions are
changed to register the iterator objects statically. The two advantages are:

 * no memory leaks when aborting from hash_iterate()
 * no calls to kmalloc/kfree, therefore a little faster/safer

Tested with 9 QEMU instances, no obvious regression found.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Simon Wunderlich authored and Greg Kroah-Hartman committed Mar 4, 2010
1 parent 4ce21a7 commit b6c3597
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 60 deletions.
6 changes: 3 additions & 3 deletions drivers/staging/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ int hardif_add_interface(char *dev, int if_num)
struct batman_if *batman_if;
struct batman_packet *batman_packet;
struct orig_node *orig_node;
struct hash_it_t *hashit = NULL;
HASHIT(hashit);

batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);

Expand Down Expand Up @@ -377,8 +377,8 @@ int hardif_add_interface(char *dev, int if_num)
* if_num */
spin_lock(&orig_hash_lock);

while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
orig_node = hashit->bucket->data;
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if (resize_orig(orig_node, if_num) == -1) {
spin_unlock(&orig_hash_lock);
goto out;
Expand Down
23 changes: 8 additions & 15 deletions drivers/staging/batman-adv/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,18 @@ void hash_destroy(struct hashtable_t *hash)
kfree(hash);
}

/* iterate though the hash. first element is selected with iter_in NULL. use
* the returned iterator to access the elements until hash_it_t returns NULL. */
/* iterate though the hash. First element is selected if an iterator
* initialized with HASHIT() is supplied as iter. Use the returned
* (or supplied) iterator to access the elements until hash_iterate returns
* NULL. */

struct hash_it_t *hash_iterate(struct hashtable_t *hash,
struct hash_it_t *iter_in)
struct hash_it_t *iter)
{
struct hash_it_t *iter;

if (!hash)
return NULL;

if (iter_in == NULL) {
iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC);
iter->index = -1;
iter->bucket = NULL;
iter->prev_bucket = NULL;
} else {
iter = iter_in;
}
if (!iter)
return NULL;

/* sanity checks first (if our bucket got deleted in the last
* iteration): */
Expand Down Expand Up @@ -139,7 +133,6 @@ struct hash_it_t *hash_iterate(struct hashtable_t *hash,
}

/* nothing to iterate over anymore */
kfree(iter);
return NULL;
}

Expand Down
5 changes: 5 additions & 0 deletions drivers/staging/batman-adv/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@

#ifndef _BATMAN_HASH_H
#define _BATMAN_HASH_H
#define HASHIT(name) struct hash_it_t name = { \
.index = -1, .bucket = NULL, \
.prev_bucket = NULL, \
.first_bucket = NULL }


typedef int (*hashdata_compare_cb)(void *, void *);
typedef int (*hashdata_choose_cb)(void *, int);
Expand Down
8 changes: 4 additions & 4 deletions drivers/staging/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,16 +221,16 @@ static bool purge_orig_node(struct orig_node *orig_node)

void purge_orig(struct work_struct *work)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct orig_node *orig_node;

spin_lock(&orig_hash_lock);

/* for all origins... */
while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
orig_node = hashit->bucket->data;
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if (purge_orig_node(orig_node)) {
hash_remove_bucket(orig_hash, hashit);
hash_remove_bucket(orig_hash, &hashit);
free_orig_node(orig_node);
}
}
Expand Down
12 changes: 6 additions & 6 deletions drivers/staging/batman-adv/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ static int proc_orig_interval_open(struct inode *inode, struct file *file)

static int proc_originators_read(struct seq_file *seq, void *offset)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct orig_node *orig_node;
struct neigh_node *neigh_node;
int batman_count = 0;
Expand Down Expand Up @@ -215,9 +215,9 @@ static int proc_originators_read(struct seq_file *seq, void *offset)
rcu_read_unlock();
spin_lock(&orig_hash_lock);

while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
while (hash_iterate(orig_hash, &hashit)) {

orig_node = hashit->bucket->data;
orig_node = hashit.bucket->data;

if (!orig_node->router)
continue;
Expand Down Expand Up @@ -413,7 +413,7 @@ static void proc_vis_read_entry(struct seq_file *seq,

static int proc_vis_read(struct seq_file *seq, void *offset)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct vis_info *info;
struct vis_info_entry *entries;
struct vis_if_list *if_entries = NULL;
Expand All @@ -440,8 +440,8 @@ static int proc_vis_read(struct seq_file *seq, void *offset)
seq_printf(seq, "digraph {\n");

spin_lock(&vis_hash_lock);
while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
info = hashit->bucket->data;
while (hash_iterate(vis_hash, &hashit)) {
info = hashit.bucket->data;
entries = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info));

Expand Down
6 changes: 3 additions & 3 deletions drivers/staging/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ static atomic_t data_ready_cond;
atomic_t exit_cond;
void slide_own_bcast_window(struct batman_if *batman_if)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct orig_node *orig_node;
TYPE_OF_WORD *word;

spin_lock(&orig_hash_lock);

while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
orig_node = hashit->bucket->data;
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);

bit_get_packet(word, 1, 0);
Expand Down
24 changes: 12 additions & 12 deletions drivers/staging/batman-adv/translation-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,18 @@ void hna_local_add(uint8_t *addr)
int hna_local_fill_buffer(unsigned char *buff, int buff_len)
{
struct hna_local_entry *hna_local_entry;
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
int i = 0;
unsigned long flags;

spin_lock_irqsave(&hna_local_hash_lock, flags);

while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
while (hash_iterate(hna_local_hash, &hashit)) {

if (buff_len < (i + 1) * ETH_ALEN)
break;

hna_local_entry = hashit->bucket->data;
hna_local_entry = hashit.bucket->data;
memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);

i++;
Expand All @@ -163,18 +163,18 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len)
int hna_local_fill_buffer_text(unsigned char *buff, int buff_len)
{
struct hna_local_entry *hna_local_entry;
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;

spin_lock_irqsave(&hna_local_hash_lock, flags);

while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
while (hash_iterate(hna_local_hash, &hashit)) {

if (buff_len < bytes_written + ETH_STR_LEN + 4)
break;

hna_local_entry = hashit->bucket->data;
hna_local_entry = hashit.bucket->data;

bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4,
" * %02x:%02x:%02x:%02x:%02x:%02x\n",
Expand Down Expand Up @@ -214,14 +214,14 @@ static void hna_local_del(struct hna_local_entry *hna_local_entry,
void hna_local_purge(struct work_struct *work)
{
struct hna_local_entry *hna_local_entry;
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
unsigned long flags;
unsigned long timeout;

spin_lock_irqsave(&hna_local_hash_lock, flags);

while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
hna_local_entry = hashit->bucket->data;
while (hash_iterate(hna_local_hash, &hashit)) {
hna_local_entry = hashit.bucket->data;

timeout = hna_local_entry->last_seen +
((LOCAL_HNA_TIMEOUT / 1000) * HZ);
Expand Down Expand Up @@ -345,17 +345,17 @@ void hna_global_add_orig(struct orig_node *orig_node,
int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
{
struct hna_global_entry *hna_global_entry;
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;

spin_lock_irqsave(&hna_global_hash_lock, flags);

while (NULL != (hashit = hash_iterate(hna_global_hash, hashit))) {
while (hash_iterate(hna_global_hash, &hashit)) {
if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10)
break;

hna_global_entry = hashit->bucket->data;
hna_global_entry = hashit.bucket->data;

bytes_written += snprintf(buff + bytes_written,
(2 * ETH_STR_LEN) + 10,
Expand Down
33 changes: 16 additions & 17 deletions drivers/staging/batman-adv/vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,12 @@ void receive_client_update_packet(struct vis_packet *vis_packet,
* Must be called with the originator hash locked */
static int find_best_vis_server(struct vis_info *info)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct orig_node *orig_node;
int best_tq = -1;

while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
orig_node = hashit->bucket->data;
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if ((orig_node != NULL) &&
(orig_node->router != NULL) &&
(orig_node->flags & VIS_SERVER) &&
Expand All @@ -297,7 +297,8 @@ static bool vis_packet_full(struct vis_info *info)
* returns 0 on success, -1 if no packet could be generated */
static int generate_vis_packet(void)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit_local);
HASHIT(hashit_global);
struct orig_node *orig_node;
struct vis_info *info = (struct vis_info *)my_vis_info;
struct vis_info_entry *entry, *entry_array;
Expand All @@ -320,13 +321,12 @@ static int generate_vis_packet(void)
return -1;
}
}
hashit = NULL;

entry_array = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info));

while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
orig_node = hashit->bucket->data;
while (hash_iterate(orig_hash, &hashit_global)) {
orig_node = hashit_global.bucket->data;
if (orig_node->router != NULL
&& compare_orig(orig_node->router->addr, orig_node->orig)
&& orig_node->batman_if
Expand All @@ -349,10 +349,9 @@ static int generate_vis_packet(void)

spin_unlock(&orig_hash_lock);

hashit = NULL;
spin_lock_irqsave(&hna_local_hash_lock, flags);
while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
hna_local_entry = hashit->bucket->data;
while (hash_iterate(hna_local_hash, &hashit_local)) {
hna_local_entry = hashit_local.bucket->data;
entry = &entry_array[info->packet.entries];
memset(entry->src, 0, ETH_ALEN);
memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN);
Expand All @@ -370,31 +369,31 @@ static int generate_vis_packet(void)

static void purge_vis_packets(void)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct vis_info *info;

while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
info = hashit->bucket->data;
while (hash_iterate(vis_hash, &hashit)) {
info = hashit.bucket->data;
if (info == my_vis_info) /* never purge own data. */
continue;
if (time_after(jiffies,
info->first_seen + (VIS_TIMEOUT/1000)*HZ)) {
hash_remove_bucket(vis_hash, hashit);
hash_remove_bucket(vis_hash, &hashit);
free_info(info);
}
}
}

static void broadcast_vis_packet(struct vis_info *info, int packet_length)
{
struct hash_it_t *hashit = NULL;
HASHIT(hashit);
struct orig_node *orig_node;

spin_lock(&orig_hash_lock);

/* send to all routers in range. */
while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
orig_node = hashit->bucket->data;
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;

/* if it's a vis server and reachable, send it. */
if (orig_node &&
Expand Down

0 comments on commit b6c3597

Please sign in to comment.