aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-01-27 15:54:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-01-27 15:54:16 -0500
commit1b1bc42c1692e9b62756323c675a44cb1a1f9dbd (patch)
treed514a2d8512fc52c15747841e2368f8f99a50787 /net/tipc
parent3365135d43f861003555c963b309672d053a2228 (diff)
parent950eabbd6ddedc1b08350b9169a6a51b130ebaaf (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) GTP fixes from Andreas Schultz (missing genl module alias, clear IP DF on transmit). 2) Netfilter needs to reflect the fwmark when sending resets, from Pau Espin Pedrol. 3) nftable dump OOPS fix from Liping Zhang. 4) Fix erroneous setting of VIRTIO_NET_HDR_F_DATA_VALID on transmit, from Rolf Neugebauer. 5) Fix build error of ipt_CLUSTERIP when procfs is disabled, from Arnd Bergmann. 6) Fix regression in handling of NETIF_F_SG in harmonize_features(), from Eric Dumazet. 7) Fix RTNL deadlock wrt. lwtunnel module loading, from David Ahern. 8) tcp_fastopen_create_child() needs to setup tp->max_window, from Alexey Kodanev. 9) Missing kmemdup() failure check in ipv6 segment routing code, from Eric Dumazet. 10) Don't execute unix_bind() under the bindlock, otherwise we deadlock with splice. From WANG Cong. 11) ip6_tnl_parse_tlv_enc_lim() potentially reallocates the skb buffer, therefore callers must reload cached header pointers into that skb. Fix from Eric Dumazet. 12) Fix various bugs in legacy IRQ fallback handling in alx driver, from Tobias Regnery. 13) Do not allow lwtunnel drivers to be unloaded while they are referenced by active instances, from Robert Shearman. 14) Fix truncated PHY LED trigger names, from Geert Uytterhoeven. 15) Fix a few regressions from virtio_net XDP support, from John Fastabend and Jakub Kicinski. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (102 commits) ISDN: eicon: silence misleading array-bounds warning net: phy: micrel: add support for KSZ8795 gtp: fix cross netns recv on gtp socket gtp: clear DF bit on GTP packet tx gtp: add genl family modules alias tcp: don't annotate mark on control socket from tcp_v6_send_response() ravb: unmap descriptors when freeing rings virtio_net: reject XDP programs using header adjustment virtio_net: use dev_kfree_skb for small buffer XDP receive r8152: check rx after napi is enabled r8152: re-schedule napi for tx r8152: avoid start_xmit to schedule napi when napi is disabled r8152: avoid start_xmit to call napi_schedule during autosuspend net: dsa: Bring back device detaching in dsa_slave_suspend() net: phy: leds: Fix truncated LED trigger names net: phy: leds: Break dependency of phy.h on phy_led_triggers.h net: phy: leds: Clear phy_num_led_triggers on failure to avoid crash net-next: ethernet: mediatek: change the compatible string Documentation: devicetree: change the mediatek ethernet compatible string bnxt_en: Fix RTNL lock usage on bnxt_get_port_module_status(). ...
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/node.c9
-rw-r--r--net/tipc/server.c48
-rw-r--r--net/tipc/subscr.c124
-rw-r--r--net/tipc/subscr.h1
4 files changed, 99 insertions, 83 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 9d2f4c2b08ab..27753325e06e 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -263,6 +263,11 @@ static void tipc_node_write_lock(struct tipc_node *n)
263 write_lock_bh(&n->lock); 263 write_lock_bh(&n->lock);
264} 264}
265 265
266static void tipc_node_write_unlock_fast(struct tipc_node *n)
267{
268 write_unlock_bh(&n->lock);
269}
270
266static void tipc_node_write_unlock(struct tipc_node *n) 271static void tipc_node_write_unlock(struct tipc_node *n)
267{ 272{
268 struct net *net = n->net; 273 struct net *net = n->net;
@@ -417,7 +422,7 @@ void tipc_node_subscribe(struct net *net, struct list_head *subscr, u32 addr)
417 } 422 }
418 tipc_node_write_lock(n); 423 tipc_node_write_lock(n);
419 list_add_tail(subscr, &n->publ_list); 424 list_add_tail(subscr, &n->publ_list);
420 tipc_node_write_unlock(n); 425 tipc_node_write_unlock_fast(n);
421 tipc_node_put(n); 426 tipc_node_put(n);
422} 427}
423 428
@@ -435,7 +440,7 @@ void tipc_node_unsubscribe(struct net *net, struct list_head *subscr, u32 addr)
435 } 440 }
436 tipc_node_write_lock(n); 441 tipc_node_write_lock(n);
437 list_del_init(subscr); 442 list_del_init(subscr);
438 tipc_node_write_unlock(n); 443 tipc_node_write_unlock_fast(n);
439 tipc_node_put(n); 444 tipc_node_put(n);
440} 445}
441 446
diff --git a/net/tipc/server.c b/net/tipc/server.c
index 215849ce453d..3cd6402e812c 100644
--- a/net/tipc/server.c
+++ b/net/tipc/server.c
@@ -86,12 +86,12 @@ struct outqueue_entry {
86static void tipc_recv_work(struct work_struct *work); 86static void tipc_recv_work(struct work_struct *work);
87static void tipc_send_work(struct work_struct *work); 87static void tipc_send_work(struct work_struct *work);
88static void tipc_clean_outqueues(struct tipc_conn *con); 88static void tipc_clean_outqueues(struct tipc_conn *con);
89static void tipc_sock_release(struct tipc_conn *con);
90 89
91static void tipc_conn_kref_release(struct kref *kref) 90static void tipc_conn_kref_release(struct kref *kref)
92{ 91{
93 struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); 92 struct tipc_conn *con = container_of(kref, struct tipc_conn, kref);
94 struct sockaddr_tipc *saddr = con->server->saddr; 93 struct tipc_server *s = con->server;
94 struct sockaddr_tipc *saddr = s->saddr;
95 struct socket *sock = con->sock; 95 struct socket *sock = con->sock;
96 struct sock *sk; 96 struct sock *sk;
97 97
@@ -103,9 +103,13 @@ static void tipc_conn_kref_release(struct kref *kref)
103 } 103 }
104 saddr->scope = -TIPC_NODE_SCOPE; 104 saddr->scope = -TIPC_NODE_SCOPE;
105 kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); 105 kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr));
106 tipc_sock_release(con);
107 sock_release(sock); 106 sock_release(sock);
108 con->sock = NULL; 107 con->sock = NULL;
108
109 spin_lock_bh(&s->idr_lock);
110 idr_remove(&s->conn_idr, con->conid);
111 s->idr_in_use--;
112 spin_unlock_bh(&s->idr_lock);
109 } 113 }
110 114
111 tipc_clean_outqueues(con); 115 tipc_clean_outqueues(con);
@@ -128,8 +132,10 @@ static struct tipc_conn *tipc_conn_lookup(struct tipc_server *s, int conid)
128 132
129 spin_lock_bh(&s->idr_lock); 133 spin_lock_bh(&s->idr_lock);
130 con = idr_find(&s->conn_idr, conid); 134 con = idr_find(&s->conn_idr, conid);
131 if (con) 135 if (con && test_bit(CF_CONNECTED, &con->flags))
132 conn_get(con); 136 conn_get(con);
137 else
138 con = NULL;
133 spin_unlock_bh(&s->idr_lock); 139 spin_unlock_bh(&s->idr_lock);
134 return con; 140 return con;
135} 141}
@@ -186,26 +192,15 @@ static void tipc_unregister_callbacks(struct tipc_conn *con)
186 write_unlock_bh(&sk->sk_callback_lock); 192 write_unlock_bh(&sk->sk_callback_lock);
187} 193}
188 194
189static void tipc_sock_release(struct tipc_conn *con)
190{
191 struct tipc_server *s = con->server;
192
193 if (con->conid)
194 s->tipc_conn_release(con->conid, con->usr_data);
195
196 tipc_unregister_callbacks(con);
197}
198
199static void tipc_close_conn(struct tipc_conn *con) 195static void tipc_close_conn(struct tipc_conn *con)
200{ 196{
201 struct tipc_server *s = con->server; 197 struct tipc_server *s = con->server;
202 198
203 if (test_and_clear_bit(CF_CONNECTED, &con->flags)) { 199 if (test_and_clear_bit(CF_CONNECTED, &con->flags)) {
200 tipc_unregister_callbacks(con);
204 201
205 spin_lock_bh(&s->idr_lock); 202 if (con->conid)
206 idr_remove(&s->conn_idr, con->conid); 203 s->tipc_conn_release(con->conid, con->usr_data);
207 s->idr_in_use--;
208 spin_unlock_bh(&s->idr_lock);
209 204
210 /* We shouldn't flush pending works as we may be in the 205 /* We shouldn't flush pending works as we may be in the
211 * thread. In fact the races with pending rx/tx work structs 206 * thread. In fact the races with pending rx/tx work structs
@@ -458,6 +453,11 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,
458 if (!con) 453 if (!con)
459 return -EINVAL; 454 return -EINVAL;
460 455
456 if (!test_bit(CF_CONNECTED, &con->flags)) {
457 conn_put(con);
458 return 0;
459 }
460
461 e = tipc_alloc_entry(data, len); 461 e = tipc_alloc_entry(data, len);
462 if (!e) { 462 if (!e) {
463 conn_put(con); 463 conn_put(con);
@@ -471,12 +471,8 @@ int tipc_conn_sendmsg(struct tipc_server *s, int conid,
471 list_add_tail(&e->list, &con->outqueue); 471 list_add_tail(&e->list, &con->outqueue);
472 spin_unlock_bh(&con->outqueue_lock); 472 spin_unlock_bh(&con->outqueue_lock);
473 473
474 if (test_bit(CF_CONNECTED, &con->flags)) { 474 if (!queue_work(s->send_wq, &con->swork))
475 if (!queue_work(s->send_wq, &con->swork))
476 conn_put(con);
477 } else {
478 conn_put(con); 475 conn_put(con);
479 }
480 return 0; 476 return 0;
481} 477}
482 478
@@ -500,7 +496,7 @@ static void tipc_send_to_sock(struct tipc_conn *con)
500 int ret; 496 int ret;
501 497
502 spin_lock_bh(&con->outqueue_lock); 498 spin_lock_bh(&con->outqueue_lock);
503 while (1) { 499 while (test_bit(CF_CONNECTED, &con->flags)) {
504 e = list_entry(con->outqueue.next, struct outqueue_entry, 500 e = list_entry(con->outqueue.next, struct outqueue_entry,
505 list); 501 list);
506 if ((struct list_head *) e == &con->outqueue) 502 if ((struct list_head *) e == &con->outqueue)
@@ -623,14 +619,12 @@ int tipc_server_start(struct tipc_server *s)
623void tipc_server_stop(struct tipc_server *s) 619void tipc_server_stop(struct tipc_server *s)
624{ 620{
625 struct tipc_conn *con; 621 struct tipc_conn *con;
626 int total = 0;
627 int id; 622 int id;
628 623
629 spin_lock_bh(&s->idr_lock); 624 spin_lock_bh(&s->idr_lock);
630 for (id = 0; total < s->idr_in_use; id++) { 625 for (id = 0; s->idr_in_use; id++) {
631 con = idr_find(&s->conn_idr, id); 626 con = idr_find(&s->conn_idr, id);
632 if (con) { 627 if (con) {
633 total++;
634 spin_unlock_bh(&s->idr_lock); 628 spin_unlock_bh(&s->idr_lock);
635 tipc_close_conn(con); 629 tipc_close_conn(con);
636 spin_lock_bh(&s->idr_lock); 630 spin_lock_bh(&s->idr_lock);
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index 0dd02244e21d..9d94e65d0894 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -54,6 +54,8 @@ struct tipc_subscriber {
54 54
55static void tipc_subscrp_delete(struct tipc_subscription *sub); 55static void tipc_subscrp_delete(struct tipc_subscription *sub);
56static void tipc_subscrb_put(struct tipc_subscriber *subscriber); 56static void tipc_subscrb_put(struct tipc_subscriber *subscriber);
57static void tipc_subscrp_put(struct tipc_subscription *subscription);
58static void tipc_subscrp_get(struct tipc_subscription *subscription);
57 59
58/** 60/**
59 * htohl - convert value to endianness used by destination 61 * htohl - convert value to endianness used by destination
@@ -123,6 +125,7 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
123{ 125{
124 struct tipc_name_seq seq; 126 struct tipc_name_seq seq;
125 127
128 tipc_subscrp_get(sub);
126 tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq); 129 tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq);
127 if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper)) 130 if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper))
128 return; 131 return;
@@ -132,30 +135,23 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
132 135
133 tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref, 136 tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref,
134 node); 137 node);
138 tipc_subscrp_put(sub);
135} 139}
136 140
137static void tipc_subscrp_timeout(unsigned long data) 141static void tipc_subscrp_timeout(unsigned long data)
138{ 142{
139 struct tipc_subscription *sub = (struct tipc_subscription *)data; 143 struct tipc_subscription *sub = (struct tipc_subscription *)data;
140 struct tipc_subscriber *subscriber = sub->subscriber;
141 144
142 /* Notify subscriber of timeout */ 145 /* Notify subscriber of timeout */
143 tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper, 146 tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
144 TIPC_SUBSCR_TIMEOUT, 0, 0); 147 TIPC_SUBSCR_TIMEOUT, 0, 0);
145 148
146 spin_lock_bh(&subscriber->lock); 149 tipc_subscrp_put(sub);
147 tipc_subscrp_delete(sub);
148 spin_unlock_bh(&subscriber->lock);
149
150 tipc_subscrb_put(subscriber);
151} 150}
152 151
153static void tipc_subscrb_kref_release(struct kref *kref) 152static void tipc_subscrb_kref_release(struct kref *kref)
154{ 153{
155 struct tipc_subscriber *subcriber = container_of(kref, 154 kfree(container_of(kref,struct tipc_subscriber, kref));
156 struct tipc_subscriber, kref);
157
158 kfree(subcriber);
159} 155}
160 156
161static void tipc_subscrb_put(struct tipc_subscriber *subscriber) 157static void tipc_subscrb_put(struct tipc_subscriber *subscriber)
@@ -168,6 +164,59 @@ static void tipc_subscrb_get(struct tipc_subscriber *subscriber)
168 kref_get(&subscriber->kref); 164 kref_get(&subscriber->kref);
169} 165}
170 166
167static void tipc_subscrp_kref_release(struct kref *kref)
168{
169 struct tipc_subscription *sub = container_of(kref,
170 struct tipc_subscription,
171 kref);
172 struct tipc_net *tn = net_generic(sub->net, tipc_net_id);
173 struct tipc_subscriber *subscriber = sub->subscriber;
174
175 spin_lock_bh(&subscriber->lock);
176 tipc_nametbl_unsubscribe(sub);
177 list_del(&sub->subscrp_list);
178 atomic_dec(&tn->subscription_count);
179 spin_unlock_bh(&subscriber->lock);
180 kfree(sub);
181 tipc_subscrb_put(subscriber);
182}
183
184static void tipc_subscrp_put(struct tipc_subscription *subscription)
185{
186 kref_put(&subscription->kref, tipc_subscrp_kref_release);
187}
188
189static void tipc_subscrp_get(struct tipc_subscription *subscription)
190{
191 kref_get(&subscription->kref);
192}
193
194/* tipc_subscrb_subscrp_delete - delete a specific subscription or all
195 * subscriptions for a given subscriber.
196 */
197static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber,
198 struct tipc_subscr *s)
199{
200 struct list_head *subscription_list = &subscriber->subscrp_list;
201 struct tipc_subscription *sub, *temp;
202
203 spin_lock_bh(&subscriber->lock);
204 list_for_each_entry_safe(sub, temp, subscription_list, subscrp_list) {
205 if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr)))
206 continue;
207
208 tipc_subscrp_get(sub);
209 spin_unlock_bh(&subscriber->lock);
210 tipc_subscrp_delete(sub);
211 tipc_subscrp_put(sub);
212 spin_lock_bh(&subscriber->lock);
213
214 if (s)
215 break;
216 }
217 spin_unlock_bh(&subscriber->lock);
218}
219
171static struct tipc_subscriber *tipc_subscrb_create(int conid) 220static struct tipc_subscriber *tipc_subscrb_create(int conid)
172{ 221{
173 struct tipc_subscriber *subscriber; 222 struct tipc_subscriber *subscriber;
@@ -177,8 +226,8 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid)
177 pr_warn("Subscriber rejected, no memory\n"); 226 pr_warn("Subscriber rejected, no memory\n");
178 return NULL; 227 return NULL;
179 } 228 }
180 kref_init(&subscriber->kref);
181 INIT_LIST_HEAD(&subscriber->subscrp_list); 229 INIT_LIST_HEAD(&subscriber->subscrp_list);
230 kref_init(&subscriber->kref);
182 subscriber->conid = conid; 231 subscriber->conid = conid;
183 spin_lock_init(&subscriber->lock); 232 spin_lock_init(&subscriber->lock);
184 233
@@ -187,55 +236,22 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid)
187 236
188static void tipc_subscrb_delete(struct tipc_subscriber *subscriber) 237static void tipc_subscrb_delete(struct tipc_subscriber *subscriber)
189{ 238{
190 struct tipc_subscription *sub, *temp; 239 tipc_subscrb_subscrp_delete(subscriber, NULL);
191 u32 timeout;
192
193 spin_lock_bh(&subscriber->lock);
194 /* Destroy any existing subscriptions for subscriber */
195 list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list,
196 subscrp_list) {
197 timeout = htohl(sub->evt.s.timeout, sub->swap);
198 if ((timeout == TIPC_WAIT_FOREVER) || del_timer(&sub->timer)) {
199 tipc_subscrp_delete(sub);
200 tipc_subscrb_put(subscriber);
201 }
202 }
203 spin_unlock_bh(&subscriber->lock);
204
205 tipc_subscrb_put(subscriber); 240 tipc_subscrb_put(subscriber);
206} 241}
207 242
208static void tipc_subscrp_delete(struct tipc_subscription *sub) 243static void tipc_subscrp_delete(struct tipc_subscription *sub)
209{ 244{
210 struct tipc_net *tn = net_generic(sub->net, tipc_net_id); 245 u32 timeout = htohl(sub->evt.s.timeout, sub->swap);
211 246
212 tipc_nametbl_unsubscribe(sub); 247 if (timeout == TIPC_WAIT_FOREVER || del_timer(&sub->timer))
213 list_del(&sub->subscrp_list); 248 tipc_subscrp_put(sub);
214 kfree(sub);
215 atomic_dec(&tn->subscription_count);
216} 249}
217 250
218static void tipc_subscrp_cancel(struct tipc_subscr *s, 251static void tipc_subscrp_cancel(struct tipc_subscr *s,
219 struct tipc_subscriber *subscriber) 252 struct tipc_subscriber *subscriber)
220{ 253{
221 struct tipc_subscription *sub, *temp; 254 tipc_subscrb_subscrp_delete(subscriber, s);
222 u32 timeout;
223
224 spin_lock_bh(&subscriber->lock);
225 /* Find first matching subscription, exit if not found */
226 list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list,
227 subscrp_list) {
228 if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) {
229 timeout = htohl(sub->evt.s.timeout, sub->swap);
230 if ((timeout == TIPC_WAIT_FOREVER) ||
231 del_timer(&sub->timer)) {
232 tipc_subscrp_delete(sub);
233 tipc_subscrb_put(subscriber);
234 }
235 break;
236 }
237 }
238 spin_unlock_bh(&subscriber->lock);
239} 255}
240 256
241static struct tipc_subscription *tipc_subscrp_create(struct net *net, 257static struct tipc_subscription *tipc_subscrp_create(struct net *net,
@@ -272,6 +288,7 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net,
272 sub->swap = swap; 288 sub->swap = swap;
273 memcpy(&sub->evt.s, s, sizeof(*s)); 289 memcpy(&sub->evt.s, s, sizeof(*s));
274 atomic_inc(&tn->subscription_count); 290 atomic_inc(&tn->subscription_count);
291 kref_init(&sub->kref);
275 return sub; 292 return sub;
276} 293}
277 294
@@ -288,17 +305,16 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s,
288 305
289 spin_lock_bh(&subscriber->lock); 306 spin_lock_bh(&subscriber->lock);
290 list_add(&sub->subscrp_list, &subscriber->subscrp_list); 307 list_add(&sub->subscrp_list, &subscriber->subscrp_list);
291 tipc_subscrb_get(subscriber);
292 sub->subscriber = subscriber; 308 sub->subscriber = subscriber;
293 tipc_nametbl_subscribe(sub); 309 tipc_nametbl_subscribe(sub);
310 tipc_subscrb_get(subscriber);
294 spin_unlock_bh(&subscriber->lock); 311 spin_unlock_bh(&subscriber->lock);
295 312
313 setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub);
296 timeout = htohl(sub->evt.s.timeout, swap); 314 timeout = htohl(sub->evt.s.timeout, swap);
297 if (timeout == TIPC_WAIT_FOREVER)
298 return;
299 315
300 setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); 316 if (timeout != TIPC_WAIT_FOREVER)
301 mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); 317 mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout));
302} 318}
303 319
304/* Handle one termination request for the subscriber */ 320/* Handle one termination request for the subscriber */
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h
index be60103082c9..ffdc214c117a 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -57,6 +57,7 @@ struct tipc_subscriber;
57 * @evt: template for events generated by subscription 57 * @evt: template for events generated by subscription
58 */ 58 */
59struct tipc_subscription { 59struct tipc_subscription {
60 struct kref kref;
60 struct tipc_subscriber *subscriber; 61 struct tipc_subscriber *subscriber;
61 struct net *net; 62 struct net *net;
62 struct timer_list timer; 63 struct timer_list timer;