aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/server.c')
-rw-r--r--net/tipc/server.c48
1 files changed, 21 insertions, 27 deletions
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);