diff options
author | Marek Lindner <lindner_marek@yahoo.de> | 2011-02-18 07:28:09 -0500 |
---|---|---|
committer | Marek Lindner <lindner_marek@yahoo.de> | 2011-03-05 06:52:00 -0500 |
commit | 7aadf889e897155c45cda230d2a6701ad1fbff61 (patch) | |
tree | 4a31df411c29844afe25ccde17d2ff9e618241c1 /net/batman-adv/vis.c | |
parent | 39901e716275da4e831b40f9e45a1b61d6a776dc (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.c | 103 |
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 */ |
70 | static int vis_info_cmp(void *data1, void *data2) | 70 | static 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 | ||
107 | static 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 */ |
108 | static void vis_data_insert_interface(const uint8_t *interface, | 137 | static 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 | ||
175 | int vis_seq_print_text(struct seq_file *seq, void *offset) | 204 | int 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) | |||
576 | static int generate_vis_packet(struct bat_priv *bat_priv) | 601 | static 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 */ |
950 | static void free_info_ref(void *data, void *arg) | 964 | static 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 | } |