aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/vis.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2011-02-18 07:28:09 -0500
committerMarek Lindner <lindner_marek@yahoo.de>2011-03-05 06:52:00 -0500
commit7aadf889e897155c45cda230d2a6701ad1fbff61 (patch)
tree4a31df411c29844afe25ccde17d2ff9e618241c1 /net/batman-adv/vis.c
parent39901e716275da4e831b40f9e45a1b61d6a776dc (diff)
batman-adv: remove extra layer between hash and hash element - hash bucket
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv/vis.c')
-rw-r--r--net/batman-adv/vis.c103
1 files changed, 59 insertions, 44 deletions
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index fc9732967dbd..d179acabb04c 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -67,11 +67,12 @@ static void free_info(struct kref *ref)
67} 67}
68 68
69/* Compare two vis packets, used by the hashing algorithm */ 69/* Compare two vis packets, used by the hashing algorithm */
70static int vis_info_cmp(void *data1, void *data2) 70static int vis_info_cmp(struct hlist_node *node, void *data2)
71{ 71{
72 struct vis_info *d1, *d2; 72 struct vis_info *d1, *d2;
73 struct vis_packet *p1, *p2; 73 struct vis_packet *p1, *p2;
74 d1 = data1; 74
75 d1 = container_of(node, struct vis_info, hash_entry);
75 d2 = data2; 76 d2 = data2;
76 p1 = (struct vis_packet *)d1->skb_packet->data; 77 p1 = (struct vis_packet *)d1->skb_packet->data;
77 p2 = (struct vis_packet *)d2->skb_packet->data; 78 p2 = (struct vis_packet *)d2->skb_packet->data;
@@ -103,6 +104,34 @@ static int vis_info_choose(void *data, int size)
103 return hash % size; 104 return hash % size;
104} 105}
105 106
107static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
108 void *data)
109{
110 struct hashtable_t *hash = bat_priv->vis_hash;
111 struct hlist_head *head;
112 struct hlist_node *node;
113 struct vis_info *vis_info, *vis_info_tmp = NULL;
114 int index;
115
116 if (!hash)
117 return NULL;
118
119 index = vis_info_choose(data, hash->size);
120 head = &hash->table[index];
121
122 rcu_read_lock();
123 hlist_for_each_entry_rcu(vis_info, node, head, hash_entry) {
124 if (!vis_info_cmp(node, data))
125 continue;
126
127 vis_info_tmp = vis_info;
128 break;
129 }
130 rcu_read_unlock();
131
132 return vis_info_tmp;
133}
134
106/* insert interface to the list of interfaces of one originator, if it 135/* insert interface to the list of interfaces of one originator, if it
107 * does not already exist in the list */ 136 * does not already exist in the list */
108static void vis_data_insert_interface(const uint8_t *interface, 137static void vis_data_insert_interface(const uint8_t *interface,
@@ -174,9 +203,8 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
174 203
175int vis_seq_print_text(struct seq_file *seq, void *offset) 204int vis_seq_print_text(struct seq_file *seq, void *offset)
176{ 205{
177 struct hlist_node *walk; 206 struct hlist_node *node;
178 struct hlist_head *head; 207 struct hlist_head *head;
179 struct element_t *bucket;
180 struct vis_info *info; 208 struct vis_info *info;
181 struct vis_packet *packet; 209 struct vis_packet *packet;
182 struct vis_info_entry *entries; 210 struct vis_info_entry *entries;
@@ -202,8 +230,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
202 for (i = 0; i < hash->size; i++) { 230 for (i = 0; i < hash->size; i++) {
203 head = &hash->table[i]; 231 head = &hash->table[i];
204 232
205 hlist_for_each_entry(bucket, walk, head, hlist) { 233 rcu_read_lock();
206 info = bucket->data; 234 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
207 packet = (struct vis_packet *)info->skb_packet->data; 235 packet = (struct vis_packet *)info->skb_packet->data;
208 entries = (struct vis_info_entry *) 236 entries = (struct vis_info_entry *)
209 ((char *)packet + sizeof(struct vis_packet)); 237 ((char *)packet + sizeof(struct vis_packet));
@@ -235,6 +263,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
235 kfree(entry); 263 kfree(entry);
236 } 264 }
237 } 265 }
266 rcu_read_unlock();
238 } 267 }
239 268
240 buff = kmalloc(buf_size, GFP_ATOMIC); 269 buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -248,8 +277,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
248 for (i = 0; i < hash->size; i++) { 277 for (i = 0; i < hash->size; i++) {
249 head = &hash->table[i]; 278 head = &hash->table[i];
250 279
251 hlist_for_each_entry(bucket, walk, head, hlist) { 280 rcu_read_lock();
252 info = bucket->data; 281 hlist_for_each_entry_rcu(info, node, head, hash_entry) {
253 packet = (struct vis_packet *)info->skb_packet->data; 282 packet = (struct vis_packet *)info->skb_packet->data;
254 entries = (struct vis_info_entry *) 283 entries = (struct vis_info_entry *)
255 ((char *)packet + sizeof(struct vis_packet)); 284 ((char *)packet + sizeof(struct vis_packet));
@@ -290,6 +319,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
290 kfree(entry); 319 kfree(entry);
291 } 320 }
292 } 321 }
322 rcu_read_unlock();
293 } 323 }
294 324
295 spin_unlock_bh(&bat_priv->vis_hash_lock); 325 spin_unlock_bh(&bat_priv->vis_hash_lock);
@@ -380,10 +410,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
380 sizeof(struct vis_packet)); 410 sizeof(struct vis_packet));
381 411
382 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN); 412 memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
383 rcu_read_lock(); 413 old_info = vis_hash_find(bat_priv, &search_elem);
384 old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
385 &search_elem);
386 rcu_read_unlock();
387 kfree_skb(search_elem.skb_packet); 414 kfree_skb(search_elem.skb_packet);
388 415
389 if (old_info) { 416 if (old_info) {
@@ -443,7 +470,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
443 470
444 /* try to add it */ 471 /* try to add it */
445 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 472 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
446 info); 473 info, &info->hash_entry);
447 if (hash_added < 0) { 474 if (hash_added < 0) {
448 /* did not work (for some reason) */ 475 /* did not work (for some reason) */
449 kref_put(&old_info->refcount, free_info); 476 kref_put(&old_info->refcount, free_info);
@@ -530,9 +557,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
530 struct vis_info *info) 557 struct vis_info *info)
531{ 558{
532 struct hashtable_t *hash = bat_priv->orig_hash; 559 struct hashtable_t *hash = bat_priv->orig_hash;
533 struct hlist_node *walk; 560 struct hlist_node *node;
534 struct hlist_head *head; 561 struct hlist_head *head;
535 struct element_t *bucket;
536 struct orig_node *orig_node; 562 struct orig_node *orig_node;
537 struct vis_packet *packet; 563 struct vis_packet *packet;
538 int best_tq = -1, i; 564 int best_tq = -1, i;
@@ -543,11 +569,10 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
543 head = &hash->table[i]; 569 head = &hash->table[i];
544 570
545 rcu_read_lock(); 571 rcu_read_lock();
546 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 572 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
547 orig_node = bucket->data;
548 if ((orig_node) && (orig_node->router) && 573 if ((orig_node) && (orig_node->router) &&
549 (orig_node->flags & VIS_SERVER) && 574 (orig_node->flags & VIS_SERVER) &&
550 (orig_node->router->tq_avg > best_tq)) { 575 (orig_node->router->tq_avg > best_tq)) {
551 best_tq = orig_node->router->tq_avg; 576 best_tq = orig_node->router->tq_avg;
552 memcpy(packet->target_orig, orig_node->orig, 577 memcpy(packet->target_orig, orig_node->orig,
553 ETH_ALEN); 578 ETH_ALEN);
@@ -576,9 +601,8 @@ static bool vis_packet_full(struct vis_info *info)
576static int generate_vis_packet(struct bat_priv *bat_priv) 601static int generate_vis_packet(struct bat_priv *bat_priv)
577{ 602{
578 struct hashtable_t *hash = bat_priv->orig_hash; 603 struct hashtable_t *hash = bat_priv->orig_hash;
579 struct hlist_node *walk; 604 struct hlist_node *node;
580 struct hlist_head *head; 605 struct hlist_head *head;
581 struct element_t *bucket;
582 struct orig_node *orig_node; 606 struct orig_node *orig_node;
583 struct neigh_node *neigh_node; 607 struct neigh_node *neigh_node;
584 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; 608 struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
@@ -610,8 +634,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
610 head = &hash->table[i]; 634 head = &hash->table[i];
611 635
612 rcu_read_lock(); 636 rcu_read_lock();
613 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 637 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
614 orig_node = bucket->data;
615 neigh_node = orig_node->router; 638 neigh_node = orig_node->router;
616 639
617 if (!neigh_node) 640 if (!neigh_node)
@@ -653,8 +676,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
653 for (i = 0; i < hash->size; i++) { 676 for (i = 0; i < hash->size; i++) {
654 head = &hash->table[i]; 677 head = &hash->table[i];
655 678
656 hlist_for_each_entry(bucket, walk, head, hlist) { 679 hlist_for_each_entry(hna_local_entry, node, head, hash_entry) {
657 hna_local_entry = bucket->data;
658 entry = (struct vis_info_entry *) 680 entry = (struct vis_info_entry *)
659 skb_put(info->skb_packet, 681 skb_put(info->skb_packet,
660 sizeof(*entry)); 682 sizeof(*entry));
@@ -680,25 +702,22 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
680{ 702{
681 int i; 703 int i;
682 struct hashtable_t *hash = bat_priv->vis_hash; 704 struct hashtable_t *hash = bat_priv->vis_hash;
683 struct hlist_node *walk, *safe; 705 struct hlist_node *node, *node_tmp;
684 struct hlist_head *head; 706 struct hlist_head *head;
685 struct element_t *bucket;
686 struct vis_info *info; 707 struct vis_info *info;
687 708
688 for (i = 0; i < hash->size; i++) { 709 for (i = 0; i < hash->size; i++) {
689 head = &hash->table[i]; 710 head = &hash->table[i];
690 711
691 hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) { 712 hlist_for_each_entry_safe(info, node, node_tmp,
692 info = bucket->data; 713 head, hash_entry) {
693
694 /* never purge own data. */ 714 /* never purge own data. */
695 if (info == bat_priv->my_vis_info) 715 if (info == bat_priv->my_vis_info)
696 continue; 716 continue;
697 717
698 if (time_after(jiffies, 718 if (time_after(jiffies,
699 info->first_seen + VIS_TIMEOUT * HZ)) { 719 info->first_seen + VIS_TIMEOUT * HZ)) {
700 hlist_del(walk); 720 hlist_del(node);
701 kfree(bucket);
702 send_list_del(info); 721 send_list_del(info);
703 kref_put(&info->refcount, free_info); 722 kref_put(&info->refcount, free_info);
704 } 723 }
@@ -710,9 +729,8 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
710 struct vis_info *info) 729 struct vis_info *info)
711{ 730{
712 struct hashtable_t *hash = bat_priv->orig_hash; 731 struct hashtable_t *hash = bat_priv->orig_hash;
713 struct hlist_node *walk; 732 struct hlist_node *node;
714 struct hlist_head *head; 733 struct hlist_head *head;
715 struct element_t *bucket;
716 struct orig_node *orig_node; 734 struct orig_node *orig_node;
717 struct vis_packet *packet; 735 struct vis_packet *packet;
718 struct sk_buff *skb; 736 struct sk_buff *skb;
@@ -729,9 +747,7 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
729 head = &hash->table[i]; 747 head = &hash->table[i];
730 748
731 rcu_read_lock(); 749 rcu_read_lock();
732 hlist_for_each_entry_rcu(bucket, walk, head, hlist) { 750 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
733 orig_node = bucket->data;
734
735 /* if it's a vis server and reachable, send it. */ 751 /* if it's a vis server and reachable, send it. */
736 if ((!orig_node) || (!orig_node->router)) 752 if ((!orig_node) || (!orig_node->router))
737 continue; 753 continue;
@@ -774,14 +790,11 @@ static void unicast_vis_packet(struct bat_priv *bat_priv,
774 790
775 spin_lock_bh(&bat_priv->orig_hash_lock); 791 spin_lock_bh(&bat_priv->orig_hash_lock);
776 rcu_read_lock(); 792 rcu_read_lock();
777 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 793 orig_node = orig_hash_find(bat_priv, packet->target_orig);
778 compare_orig, choose_orig,
779 packet->target_orig));
780 794
781 if (!orig_node) 795 if (!orig_node)
782 goto unlock; 796 goto unlock;
783 797
784 kref_get(&orig_node->refcount);
785 neigh_node = orig_node->router; 798 neigh_node = orig_node->router;
786 799
787 if (!neigh_node) 800 if (!neigh_node)
@@ -925,7 +938,8 @@ int vis_init(struct bat_priv *bat_priv)
925 INIT_LIST_HEAD(&bat_priv->vis_send_list); 938 INIT_LIST_HEAD(&bat_priv->vis_send_list);
926 939
927 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, 940 hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
928 bat_priv->my_vis_info); 941 bat_priv->my_vis_info,
942 &bat_priv->my_vis_info->hash_entry);
929 if (hash_added < 0) { 943 if (hash_added < 0) {
930 pr_err("Can't add own vis packet into hash\n"); 944 pr_err("Can't add own vis packet into hash\n");
931 /* not in hash, need to remove it manually. */ 945 /* not in hash, need to remove it manually. */
@@ -947,10 +961,11 @@ err:
947} 961}
948 962
949/* Decrease the reference count on a hash item info */ 963/* Decrease the reference count on a hash item info */
950static void free_info_ref(void *data, void *arg) 964static void free_info_ref(struct hlist_node *node, void *arg)
951{ 965{
952 struct vis_info *info = data; 966 struct vis_info *info;
953 967
968 info = container_of(node, struct vis_info, hash_entry);
954 send_list_del(info); 969 send_list_del(info);
955 kref_put(&info->refcount, free_info); 970 kref_put(&info->refcount, free_info);
956} 971}