diff options
Diffstat (limited to 'net/tipc/server.c')
-rw-r--r-- | net/tipc/server.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/net/tipc/server.c b/net/tipc/server.c index eadd4ed45905..ab6183cdb121 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
@@ -37,11 +37,13 @@ | |||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "socket.h" | 38 | #include "socket.h" |
39 | #include <net/sock.h> | 39 | #include <net/sock.h> |
40 | #include <linux/module.h> | ||
40 | 41 | ||
41 | /* Number of messages to send before rescheduling */ | 42 | /* Number of messages to send before rescheduling */ |
42 | #define MAX_SEND_MSG_COUNT 25 | 43 | #define MAX_SEND_MSG_COUNT 25 |
43 | #define MAX_RECV_MSG_COUNT 25 | 44 | #define MAX_RECV_MSG_COUNT 25 |
44 | #define CF_CONNECTED 1 | 45 | #define CF_CONNECTED 1 |
46 | #define CF_SERVER 2 | ||
45 | 47 | ||
46 | #define sock2con(x) ((struct tipc_conn *)(x)->sk_user_data) | 48 | #define sock2con(x) ((struct tipc_conn *)(x)->sk_user_data) |
47 | 49 | ||
@@ -88,9 +90,19 @@ static void tipc_clean_outqueues(struct tipc_conn *con); | |||
88 | static void tipc_conn_kref_release(struct kref *kref) | 90 | static void tipc_conn_kref_release(struct kref *kref) |
89 | { | 91 | { |
90 | struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); | 92 | struct tipc_conn *con = container_of(kref, struct tipc_conn, kref); |
93 | struct sockaddr_tipc *saddr = con->server->saddr; | ||
94 | struct socket *sock = con->sock; | ||
95 | struct sock *sk; | ||
91 | 96 | ||
92 | if (con->sock) { | 97 | if (sock) { |
93 | tipc_sock_release_local(con->sock); | 98 | sk = sock->sk; |
99 | if (test_bit(CF_SERVER, &con->flags)) { | ||
100 | __module_get(sock->ops->owner); | ||
101 | __module_get(sk->sk_prot_creator->owner); | ||
102 | } | ||
103 | saddr->scope = -TIPC_NODE_SCOPE; | ||
104 | kernel_bind(sock, (struct sockaddr *)saddr, sizeof(*saddr)); | ||
105 | sk_release_kernel(sk); | ||
94 | con->sock = NULL; | 106 | con->sock = NULL; |
95 | } | 107 | } |
96 | 108 | ||
@@ -281,7 +293,7 @@ static int tipc_accept_from_sock(struct tipc_conn *con) | |||
281 | struct tipc_conn *newcon; | 293 | struct tipc_conn *newcon; |
282 | int ret; | 294 | int ret; |
283 | 295 | ||
284 | ret = tipc_sock_accept_local(sock, &newsock, O_NONBLOCK); | 296 | ret = kernel_accept(sock, &newsock, O_NONBLOCK); |
285 | if (ret < 0) | 297 | if (ret < 0) |
286 | return ret; | 298 | return ret; |
287 | 299 | ||
@@ -309,9 +321,12 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) | |||
309 | struct socket *sock = NULL; | 321 | struct socket *sock = NULL; |
310 | int ret; | 322 | int ret; |
311 | 323 | ||
312 | ret = tipc_sock_create_local(s->net, s->type, &sock); | 324 | ret = sock_create_kern(AF_TIPC, SOCK_SEQPACKET, 0, &sock); |
313 | if (ret < 0) | 325 | if (ret < 0) |
314 | return NULL; | 326 | return NULL; |
327 | |||
328 | sk_change_net(sock->sk, s->net); | ||
329 | |||
315 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, | 330 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, |
316 | (char *)&s->imp, sizeof(s->imp)); | 331 | (char *)&s->imp, sizeof(s->imp)); |
317 | if (ret < 0) | 332 | if (ret < 0) |
@@ -337,11 +352,31 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) | |||
337 | pr_err("Unknown socket type %d\n", s->type); | 352 | pr_err("Unknown socket type %d\n", s->type); |
338 | goto create_err; | 353 | goto create_err; |
339 | } | 354 | } |
355 | |||
356 | /* As server's listening socket owner and creator is the same module, | ||
357 | * we have to decrease TIPC module reference count to guarantee that | ||
358 | * it remains zero after the server socket is created, otherwise, | ||
359 | * executing "rmmod" command is unable to make TIPC module deleted | ||
360 | * after TIPC module is inserted successfully. | ||
361 | * | ||
362 | * However, the reference count is ever increased twice in | ||
363 | * sock_create_kern(): one is to increase the reference count of owner | ||
364 | * of TIPC socket's proto_ops struct; another is to increment the | ||
365 | * reference count of owner of TIPC proto struct. Therefore, we must | ||
366 | * decrement the module reference count twice to ensure that it keeps | ||
367 | * zero after server's listening socket is created. Of course, we | ||
368 | * must bump the module reference count twice as well before the socket | ||
369 | * is closed. | ||
370 | */ | ||
371 | module_put(sock->ops->owner); | ||
372 | module_put(sock->sk->sk_prot_creator->owner); | ||
373 | set_bit(CF_SERVER, &con->flags); | ||
374 | |||
340 | return sock; | 375 | return sock; |
341 | 376 | ||
342 | create_err: | 377 | create_err: |
343 | sock_release(sock); | 378 | kernel_sock_shutdown(sock, SHUT_RDWR); |
344 | con->sock = NULL; | 379 | sk_release_kernel(sock->sk); |
345 | return NULL; | 380 | return NULL; |
346 | } | 381 | } |
347 | 382 | ||