diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/phonet/socket.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/phonet/socket.c')
-rw-r--r-- | net/phonet/socket.c | 83 |
1 files changed, 68 insertions, 15 deletions
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index aa5b5a972bff..c785bfd0744f 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * 02110-1301 USA | 23 | * 02110-1301 USA |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/gfp.h> | ||
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
27 | #include <linux/net.h> | 28 | #include <linux/net.h> |
28 | #include <linux/poll.h> | 29 | #include <linux/poll.h> |
@@ -45,13 +46,28 @@ static int pn_socket_release(struct socket *sock) | |||
45 | return 0; | 46 | return 0; |
46 | } | 47 | } |
47 | 48 | ||
49 | #define PN_HASHSIZE 16 | ||
50 | #define PN_HASHMASK (PN_HASHSIZE-1) | ||
51 | |||
52 | |||
48 | static struct { | 53 | static struct { |
49 | struct hlist_head hlist; | 54 | struct hlist_head hlist[PN_HASHSIZE]; |
50 | spinlock_t lock; | 55 | spinlock_t lock; |
51 | } pnsocks = { | 56 | } pnsocks; |
52 | .hlist = HLIST_HEAD_INIT, | 57 | |
53 | .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), | 58 | void __init pn_sock_init(void) |
54 | }; | 59 | { |
60 | unsigned i; | ||
61 | |||
62 | for (i = 0; i < PN_HASHSIZE; i++) | ||
63 | INIT_HLIST_HEAD(pnsocks.hlist + i); | ||
64 | spin_lock_init(&pnsocks.lock); | ||
65 | } | ||
66 | |||
67 | static struct hlist_head *pn_hash_list(u16 obj) | ||
68 | { | ||
69 | return pnsocks.hlist + (obj & PN_HASHMASK); | ||
70 | } | ||
55 | 71 | ||
56 | /* | 72 | /* |
57 | * Find address based on socket address, match only certain fields. | 73 | * Find address based on socket address, match only certain fields. |
@@ -64,10 +80,11 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) | |||
64 | struct sock *rval = NULL; | 80 | struct sock *rval = NULL; |
65 | u16 obj = pn_sockaddr_get_object(spn); | 81 | u16 obj = pn_sockaddr_get_object(spn); |
66 | u8 res = spn->spn_resource; | 82 | u8 res = spn->spn_resource; |
83 | struct hlist_head *hlist = pn_hash_list(obj); | ||
67 | 84 | ||
68 | spin_lock_bh(&pnsocks.lock); | 85 | spin_lock_bh(&pnsocks.lock); |
69 | 86 | ||
70 | sk_for_each(sknode, node, &pnsocks.hlist) { | 87 | sk_for_each(sknode, node, hlist) { |
71 | struct pn_sock *pn = pn_sk(sknode); | 88 | struct pn_sock *pn = pn_sk(sknode); |
72 | BUG_ON(!pn->sobject); /* unbound socket */ | 89 | BUG_ON(!pn->sobject); /* unbound socket */ |
73 | 90 | ||
@@ -82,8 +99,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) | |||
82 | if (pn->resource != res) | 99 | if (pn->resource != res) |
83 | continue; | 100 | continue; |
84 | } | 101 | } |
85 | if (pn_addr(pn->sobject) | 102 | if (pn_addr(pn->sobject) && |
86 | && pn_addr(pn->sobject) != pn_addr(obj)) | 103 | pn_addr(pn->sobject) != pn_addr(obj)) |
87 | continue; | 104 | continue; |
88 | 105 | ||
89 | rval = sknode; | 106 | rval = sknode; |
@@ -94,13 +111,44 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) | |||
94 | spin_unlock_bh(&pnsocks.lock); | 111 | spin_unlock_bh(&pnsocks.lock); |
95 | 112 | ||
96 | return rval; | 113 | return rval; |
114 | } | ||
115 | |||
116 | /* Deliver a broadcast packet (only in bottom-half) */ | ||
117 | void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) | ||
118 | { | ||
119 | struct hlist_head *hlist = pnsocks.hlist; | ||
120 | unsigned h; | ||
121 | |||
122 | spin_lock(&pnsocks.lock); | ||
123 | for (h = 0; h < PN_HASHSIZE; h++) { | ||
124 | struct hlist_node *node; | ||
125 | struct sock *sknode; | ||
126 | |||
127 | sk_for_each(sknode, node, hlist) { | ||
128 | struct sk_buff *clone; | ||
129 | |||
130 | if (!net_eq(sock_net(sknode), net)) | ||
131 | continue; | ||
132 | if (!sock_flag(sknode, SOCK_BROADCAST)) | ||
133 | continue; | ||
97 | 134 | ||
135 | clone = skb_clone(skb, GFP_ATOMIC); | ||
136 | if (clone) { | ||
137 | sock_hold(sknode); | ||
138 | sk_receive_skb(sknode, clone, 0); | ||
139 | } | ||
140 | } | ||
141 | hlist++; | ||
142 | } | ||
143 | spin_unlock(&pnsocks.lock); | ||
98 | } | 144 | } |
99 | 145 | ||
100 | void pn_sock_hash(struct sock *sk) | 146 | void pn_sock_hash(struct sock *sk) |
101 | { | 147 | { |
148 | struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); | ||
149 | |||
102 | spin_lock_bh(&pnsocks.lock); | 150 | spin_lock_bh(&pnsocks.lock); |
103 | sk_add_node(sk, &pnsocks.hlist); | 151 | sk_add_node(sk, hlist); |
104 | spin_unlock_bh(&pnsocks.lock); | 152 | spin_unlock_bh(&pnsocks.lock); |
105 | } | 153 | } |
106 | EXPORT_SYMBOL(pn_sock_hash); | 154 | EXPORT_SYMBOL(pn_sock_hash); |
@@ -416,15 +464,20 @@ EXPORT_SYMBOL(pn_sock_get_port); | |||
416 | static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) | 464 | static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) |
417 | { | 465 | { |
418 | struct net *net = seq_file_net(seq); | 466 | struct net *net = seq_file_net(seq); |
467 | struct hlist_head *hlist = pnsocks.hlist; | ||
419 | struct hlist_node *node; | 468 | struct hlist_node *node; |
420 | struct sock *sknode; | 469 | struct sock *sknode; |
470 | unsigned h; | ||
421 | 471 | ||
422 | sk_for_each(sknode, node, &pnsocks.hlist) { | 472 | for (h = 0; h < PN_HASHSIZE; h++) { |
423 | if (!net_eq(net, sock_net(sknode))) | 473 | sk_for_each(sknode, node, hlist) { |
424 | continue; | 474 | if (!net_eq(net, sock_net(sknode))) |
425 | if (!pos) | 475 | continue; |
426 | return sknode; | 476 | if (!pos) |
427 | pos--; | 477 | return sknode; |
478 | pos--; | ||
479 | } | ||
480 | hlist++; | ||
428 | } | 481 | } |
429 | return NULL; | 482 | return NULL; |
430 | } | 483 | } |