diff options
Diffstat (limited to 'net/tipc/server.c')
| -rw-r--r-- | net/tipc/server.c | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/net/tipc/server.c b/net/tipc/server.c index eadd4ed45905..77ff03ed1e18 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 | sock_release(sock); | ||
| 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,7 +321,7 @@ 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(s->net, AF_TIPC, SOCK_SEQPACKET, 0, &sock, 1); |
| 313 | if (ret < 0) | 325 | if (ret < 0) |
| 314 | return NULL; | 326 | return NULL; |
| 315 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, | 327 | ret = kernel_setsockopt(sock, SOL_TIPC, TIPC_IMPORTANCE, |
| @@ -337,11 +349,31 @@ static struct socket *tipc_create_listen_sock(struct tipc_conn *con) | |||
| 337 | pr_err("Unknown socket type %d\n", s->type); | 349 | pr_err("Unknown socket type %d\n", s->type); |
| 338 | goto create_err; | 350 | goto create_err; |
| 339 | } | 351 | } |
| 352 | |||
| 353 | /* As server's listening socket owner and creator is the same module, | ||
| 354 | * we have to decrease TIPC module reference count to guarantee that | ||
| 355 | * it remains zero after the server socket is created, otherwise, | ||
| 356 | * executing "rmmod" command is unable to make TIPC module deleted | ||
| 357 | * after TIPC module is inserted successfully. | ||
| 358 | * | ||
| 359 | * However, the reference count is ever increased twice in | ||
| 360 | * sock_create_kern(): one is to increase the reference count of owner | ||
| 361 | * of TIPC socket's proto_ops struct; another is to increment the | ||
| 362 | * reference count of owner of TIPC proto struct. Therefore, we must | ||
| 363 | * decrement the module reference count twice to ensure that it keeps | ||
| 364 | * zero after server's listening socket is created. Of course, we | ||
| 365 | * must bump the module reference count twice as well before the socket | ||
| 366 | * is closed. | ||
| 367 | */ | ||
| 368 | module_put(sock->ops->owner); | ||
| 369 | module_put(sock->sk->sk_prot_creator->owner); | ||
| 370 | set_bit(CF_SERVER, &con->flags); | ||
| 371 | |||
| 340 | return sock; | 372 | return sock; |
| 341 | 373 | ||
| 342 | create_err: | 374 | create_err: |
| 375 | kernel_sock_shutdown(sock, SHUT_RDWR); | ||
| 343 | sock_release(sock); | 376 | sock_release(sock); |
| 344 | con->sock = NULL; | ||
| 345 | return NULL; | 377 | return NULL; |
| 346 | } | 378 | } |
| 347 | 379 | ||
