Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Phonet: put sockets in a hash table

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Rémi Denis-Courmont and committed by
David S. Miller
6b0d07ba 4a9b5e50

+56 -25
+1
include/net/phonet/phonet.h
··· 46 46 47 47 extern const struct proto_ops phonet_dgram_ops; 48 48 49 + void pn_sock_init(void); 49 50 struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *sa); 50 51 void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb); 51 52 void phonet_get_local_port_range(int *min, int *max);
+1
net/phonet/af_phonet.c
··· 481 481 if (err) 482 482 return err; 483 483 484 + pn_sock_init(); 484 485 err = sock_register(&phonet_proto_family); 485 486 if (err) { 486 487 printk(KERN_ALERT
+54 -25
net/phonet/socket.c
··· 45 45 return 0; 46 46 } 47 47 48 + #define PN_HASHSIZE 16 49 + #define PN_HASHMASK (PN_HASHSIZE-1) 50 + 51 + 48 52 static struct { 49 - struct hlist_head hlist; 53 + struct hlist_head hlist[PN_HASHSIZE]; 50 54 spinlock_t lock; 51 - } pnsocks = { 52 - .hlist = HLIST_HEAD_INIT, 53 - .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), 54 - }; 55 + } pnsocks; 56 + 57 + void __init pn_sock_init(void) 58 + { 59 + unsigned i; 60 + 61 + for (i = 0; i < PN_HASHSIZE; i++) 62 + INIT_HLIST_HEAD(pnsocks.hlist + i); 63 + spin_lock_init(&pnsocks.lock); 64 + } 65 + 66 + static struct hlist_head *pn_hash_list(u16 obj) 67 + { 68 + return pnsocks.hlist + (obj & PN_HASHMASK); 69 + } 55 70 56 71 /* 57 72 * Find address based on socket address, match only certain fields. ··· 79 64 struct sock *rval = NULL; 80 65 u16 obj = pn_sockaddr_get_object(spn); 81 66 u8 res = spn->spn_resource; 67 + struct hlist_head *hlist = pn_hash_list(obj); 82 68 83 69 spin_lock_bh(&pnsocks.lock); 84 70 85 - sk_for_each(sknode, node, &pnsocks.hlist) { 71 + sk_for_each(sknode, node, hlist) { 86 72 struct pn_sock *pn = pn_sk(sknode); 87 73 BUG_ON(!pn->sobject); /* unbound socket */ 88 74 ··· 115 99 /* Deliver a broadcast packet (only in bottom-half) */ 116 100 void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) 117 101 { 118 - struct hlist_node *node; 119 - struct sock *sknode; 102 + struct hlist_head *hlist = pnsocks.hlist; 103 + unsigned h; 120 104 121 105 spin_lock(&pnsocks.lock); 122 - sk_for_each(sknode, node, &pnsocks.hlist) { 123 - struct sk_buff *clone; 106 + for (h = 0; h < PN_HASHSIZE; h++) { 107 + struct hlist_node *node; 108 + struct sock *sknode; 124 109 125 - if (!net_eq(sock_net(sknode), net)) 126 - continue; 127 - if (!sock_flag(sknode, SOCK_BROADCAST)) 128 - continue; 110 + sk_for_each(sknode, node, hlist) { 111 + struct sk_buff *clone; 129 112 130 - clone = skb_clone(skb, GFP_ATOMIC); 131 - if (clone) { 132 - sock_hold(sknode); 133 - sk_receive_skb(sknode, clone, 0); 113 + if (!net_eq(sock_net(sknode), net)) 114 + continue; 115 + if (!sock_flag(sknode, SOCK_BROADCAST)) 116 + continue; 117 + 118 + clone = skb_clone(skb, GFP_ATOMIC); 119 + if (clone) { 120 + sock_hold(sknode); 121 + sk_receive_skb(sknode, clone, 0); 122 + } 134 123 } 124 + hlist++; 135 125 } 136 126 spin_unlock(&pnsocks.lock); 137 127 } 138 128 139 129 void pn_sock_hash(struct sock *sk) 140 130 { 131 + struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); 132 + 141 133 spin_lock_bh(&pnsocks.lock); 142 - sk_add_node(sk, &pnsocks.hlist); 134 + sk_add_node(sk, hlist); 143 135 spin_unlock_bh(&pnsocks.lock); 144 136 } 145 137 EXPORT_SYMBOL(pn_sock_hash); ··· 463 439 static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) 464 440 { 465 441 struct net *net = seq_file_net(seq); 442 + struct hlist_head *hlist = pnsocks.hlist; 466 443 struct hlist_node *node; 467 444 struct sock *sknode; 445 + unsigned h; 468 446 469 - sk_for_each(sknode, node, &pnsocks.hlist) { 470 - if (!net_eq(net, sock_net(sknode))) 471 - continue; 472 - if (!pos) 473 - return sknode; 474 - pos--; 447 + for (h = 0; h < PN_HASHSIZE; h++) { 448 + sk_for_each(sknode, node, hlist) { 449 + if (!net_eq(net, sock_net(sknode))) 450 + continue; 451 + if (!pos) 452 + return sknode; 453 + pos--; 454 + } 455 + hlist++; 475 456 } 476 457 return NULL; 477 458 }