.. | .. |
---|
40 | 40 | #include "socket.h" |
---|
41 | 41 | #include "addr.h" |
---|
42 | 42 | #include "msg.h" |
---|
| 43 | +#include "bearer.h" |
---|
43 | 44 | #include <net/sock.h> |
---|
44 | 45 | #include <linux/module.h> |
---|
45 | 46 | |
---|
.. | .. |
---|
47 | 48 | #define MAX_SEND_MSG_COUNT 25 |
---|
48 | 49 | #define MAX_RECV_MSG_COUNT 25 |
---|
49 | 50 | #define CF_CONNECTED 1 |
---|
50 | | -#define CF_SERVER 2 |
---|
51 | 51 | |
---|
52 | 52 | #define TIPC_SERVER_NAME_LEN 32 |
---|
53 | 53 | |
---|
.. | .. |
---|
57 | 57 | * @idr_lock: protect the connection identifier set |
---|
58 | 58 | * @idr_in_use: amount of allocated identifier entry |
---|
59 | 59 | * @net: network namspace instance |
---|
60 | | - * @rcvbuf_cache: memory cache of server receive buffer |
---|
| 60 | + * @awork: accept work item |
---|
61 | 61 | * @rcv_wq: receive workqueue |
---|
62 | 62 | * @send_wq: send workqueue |
---|
63 | | - * @max_rcvbuf_size: maximum permitted receive message length |
---|
64 | | - * @tipc_conn_new: callback will be called when new connection is incoming |
---|
65 | | - * @tipc_conn_release: callback will be called before releasing the connection |
---|
66 | | - * @tipc_conn_recvmsg: callback will be called when message arrives |
---|
| 63 | + * @listener: topsrv listener socket |
---|
67 | 64 | * @name: server name |
---|
68 | | - * @imp: message importance |
---|
69 | | - * @type: socket type |
---|
70 | 65 | */ |
---|
71 | 66 | struct tipc_topsrv { |
---|
72 | 67 | struct idr conn_idr; |
---|
.. | .. |
---|
76 | 71 | struct work_struct awork; |
---|
77 | 72 | struct workqueue_struct *rcv_wq; |
---|
78 | 73 | struct workqueue_struct *send_wq; |
---|
79 | | - int max_rcvbuf_size; |
---|
80 | 74 | struct socket *listener; |
---|
81 | 75 | char name[TIPC_SERVER_NAME_LEN]; |
---|
82 | 76 | }; |
---|
.. | .. |
---|
90 | 84 | * @server: pointer to connected server |
---|
91 | 85 | * @sub_list: lsit to all pertaing subscriptions |
---|
92 | 86 | * @sub_lock: lock protecting the subscription list |
---|
93 | | - * @outqueue_lock: control access to the outqueue |
---|
94 | 87 | * @rwork: receive work item |
---|
95 | | - * @rx_action: what to do when connection socket is active |
---|
96 | 88 | * @outqueue: pointer to first outbound message in queue |
---|
97 | 89 | * @outqueue_lock: control access to the outqueue |
---|
98 | 90 | * @swork: send work item |
---|
.. | .. |
---|
184 | 176 | conn_put(con); |
---|
185 | 177 | } |
---|
186 | 178 | |
---|
187 | | -static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s) |
---|
| 179 | +static struct tipc_conn *tipc_conn_alloc(struct tipc_topsrv *s, struct socket *sock) |
---|
188 | 180 | { |
---|
189 | 181 | struct tipc_conn *con; |
---|
190 | 182 | int ret; |
---|
.. | .. |
---|
210 | 202 | } |
---|
211 | 203 | con->conid = ret; |
---|
212 | 204 | s->idr_in_use++; |
---|
213 | | - spin_unlock_bh(&s->idr_lock); |
---|
214 | 205 | |
---|
215 | 206 | set_bit(CF_CONNECTED, &con->flags); |
---|
216 | 207 | con->server = s; |
---|
| 208 | + con->sock = sock; |
---|
| 209 | + conn_get(con); |
---|
| 210 | + spin_unlock_bh(&s->idr_lock); |
---|
217 | 211 | |
---|
218 | 212 | return con; |
---|
219 | 213 | } |
---|
.. | .. |
---|
244 | 238 | if (!s || !memcmp(s, &sub->evt.s, sizeof(*s))) { |
---|
245 | 239 | tipc_sub_unsubscribe(sub); |
---|
246 | 240 | atomic_dec(&tn->subscription_count); |
---|
247 | | - } else if (s) { |
---|
248 | | - break; |
---|
| 241 | + if (s) |
---|
| 242 | + break; |
---|
249 | 243 | } |
---|
250 | 244 | } |
---|
251 | 245 | spin_unlock_bh(&con->sub_lock); |
---|
.. | .. |
---|
369 | 363 | { |
---|
370 | 364 | struct tipc_net *tn = tipc_net(srv->net); |
---|
371 | 365 | struct tipc_subscription *sub; |
---|
| 366 | + u32 s_filter = tipc_sub_read(s, filter); |
---|
372 | 367 | |
---|
373 | | - if (tipc_sub_read(s, filter) & TIPC_SUB_CANCEL) { |
---|
374 | | - s->filter &= __constant_ntohl(~TIPC_SUB_CANCEL); |
---|
| 368 | + if (s_filter & TIPC_SUB_CANCEL) { |
---|
| 369 | + tipc_sub_write(s, filter, s_filter & ~TIPC_SUB_CANCEL); |
---|
375 | 370 | tipc_conn_delete_sub(con, s); |
---|
376 | 371 | return 0; |
---|
377 | 372 | } |
---|
.. | .. |
---|
401 | 396 | iov.iov_base = &s; |
---|
402 | 397 | iov.iov_len = sizeof(s); |
---|
403 | 398 | msg.msg_name = NULL; |
---|
404 | | - iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, iov.iov_len); |
---|
| 399 | + iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, iov.iov_len); |
---|
405 | 400 | ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT); |
---|
406 | 401 | if (ret == -EWOULDBLOCK) |
---|
407 | 402 | return -EWOULDBLOCK; |
---|
.. | .. |
---|
457 | 452 | static void tipc_topsrv_accept(struct work_struct *work) |
---|
458 | 453 | { |
---|
459 | 454 | struct tipc_topsrv *srv = container_of(work, struct tipc_topsrv, awork); |
---|
460 | | - struct socket *lsock = srv->listener; |
---|
461 | | - struct socket *newsock; |
---|
| 455 | + struct socket *newsock, *lsock; |
---|
462 | 456 | struct tipc_conn *con; |
---|
463 | 457 | struct sock *newsk; |
---|
464 | 458 | int ret; |
---|
| 459 | + |
---|
| 460 | + spin_lock_bh(&srv->idr_lock); |
---|
| 461 | + if (!srv->listener) { |
---|
| 462 | + spin_unlock_bh(&srv->idr_lock); |
---|
| 463 | + return; |
---|
| 464 | + } |
---|
| 465 | + lsock = srv->listener; |
---|
| 466 | + spin_unlock_bh(&srv->idr_lock); |
---|
465 | 467 | |
---|
466 | 468 | while (1) { |
---|
467 | 469 | ret = kernel_accept(lsock, &newsock, O_NONBLOCK); |
---|
468 | 470 | if (ret < 0) |
---|
469 | 471 | return; |
---|
470 | | - con = tipc_conn_alloc(srv); |
---|
| 472 | + con = tipc_conn_alloc(srv, newsock); |
---|
471 | 473 | if (IS_ERR(con)) { |
---|
472 | 474 | ret = PTR_ERR(con); |
---|
473 | 475 | sock_release(newsock); |
---|
.. | .. |
---|
479 | 481 | newsk->sk_data_ready = tipc_conn_data_ready; |
---|
480 | 482 | newsk->sk_write_space = tipc_conn_write_space; |
---|
481 | 483 | newsk->sk_user_data = con; |
---|
482 | | - con->sock = newsock; |
---|
483 | 484 | write_unlock_bh(&newsk->sk_callback_lock); |
---|
484 | 485 | |
---|
485 | 486 | /* Wake up receive process in case of 'SYN+' message */ |
---|
486 | 487 | newsk->sk_data_ready(newsk); |
---|
| 488 | + conn_put(con); |
---|
487 | 489 | } |
---|
488 | 490 | } |
---|
489 | 491 | |
---|
490 | | -/* tipc_toprsv_listener_data_ready - interrupt callback with connection request |
---|
| 492 | +/* tipc_topsrv_listener_data_ready - interrupt callback with connection request |
---|
491 | 493 | * The queued job is launched into tipc_topsrv_accept() |
---|
492 | 494 | */ |
---|
493 | 495 | static void tipc_topsrv_listener_data_ready(struct sock *sk) |
---|
.. | .. |
---|
496 | 498 | |
---|
497 | 499 | read_lock_bh(&sk->sk_callback_lock); |
---|
498 | 500 | srv = sk->sk_user_data; |
---|
499 | | - if (srv->listener) |
---|
| 501 | + if (srv) |
---|
500 | 502 | queue_work(srv->rcv_wq, &srv->awork); |
---|
501 | 503 | read_unlock_bh(&sk->sk_callback_lock); |
---|
502 | 504 | } |
---|
503 | 505 | |
---|
504 | 506 | static int tipc_topsrv_create_listener(struct tipc_topsrv *srv) |
---|
505 | 507 | { |
---|
506 | | - int imp = TIPC_CRITICAL_IMPORTANCE; |
---|
507 | 508 | struct socket *lsock = NULL; |
---|
508 | 509 | struct sockaddr_tipc saddr; |
---|
509 | 510 | struct sock *sk; |
---|
.. | .. |
---|
520 | 521 | sk->sk_user_data = srv; |
---|
521 | 522 | write_unlock_bh(&sk->sk_callback_lock); |
---|
522 | 523 | |
---|
523 | | - rc = kernel_setsockopt(lsock, SOL_TIPC, TIPC_IMPORTANCE, |
---|
524 | | - (char *)&imp, sizeof(imp)); |
---|
| 524 | + lock_sock(sk); |
---|
| 525 | + rc = tsk_set_importance(sk, TIPC_CRITICAL_IMPORTANCE); |
---|
| 526 | + release_sock(sk); |
---|
525 | 527 | if (rc < 0) |
---|
526 | 528 | goto err; |
---|
527 | 529 | |
---|
.. | .. |
---|
575 | 577 | sub.seq.upper = upper; |
---|
576 | 578 | sub.timeout = TIPC_WAIT_FOREVER; |
---|
577 | 579 | sub.filter = filter; |
---|
578 | | - *(u32 *)&sub.usr_handle = port; |
---|
| 580 | + *(u64 *)&sub.usr_handle = (u64)port; |
---|
579 | 581 | |
---|
580 | | - con = tipc_conn_alloc(tipc_topsrv(net)); |
---|
| 582 | + con = tipc_conn_alloc(tipc_topsrv(net), NULL); |
---|
581 | 583 | if (IS_ERR(con)) |
---|
582 | 584 | return false; |
---|
583 | 585 | |
---|
584 | 586 | *conid = con->conid; |
---|
585 | | - con->sock = NULL; |
---|
586 | 587 | rc = tipc_conn_rcv_sub(tipc_topsrv(net), con, &sub); |
---|
587 | | - if (rc >= 0) |
---|
588 | | - return true; |
---|
| 588 | + if (rc) |
---|
| 589 | + conn_put(con); |
---|
| 590 | + |
---|
589 | 591 | conn_put(con); |
---|
590 | | - return false; |
---|
| 592 | + return !rc; |
---|
591 | 593 | } |
---|
592 | 594 | |
---|
593 | 595 | void tipc_topsrv_kern_unsubscr(struct net *net, int conid) |
---|
.. | .. |
---|
619 | 621 | memcpy(msg_data(buf_msg(skb)), evt, sizeof(*evt)); |
---|
620 | 622 | skb_queue_head_init(&evtq); |
---|
621 | 623 | __skb_queue_tail(&evtq, skb); |
---|
| 624 | + tipc_loopback_trace(net, &evtq); |
---|
622 | 625 | tipc_sk_rcv(net, &evtq); |
---|
623 | 626 | } |
---|
624 | 627 | |
---|
.. | .. |
---|
658 | 661 | return -ENOMEM; |
---|
659 | 662 | |
---|
660 | 663 | srv->net = net; |
---|
661 | | - srv->max_rcvbuf_size = sizeof(struct tipc_subscr); |
---|
662 | 664 | INIT_WORK(&srv->awork, tipc_topsrv_accept); |
---|
663 | 665 | |
---|
664 | 666 | strscpy(srv->name, name, sizeof(srv->name)); |
---|
.. | .. |
---|
706 | 708 | __module_get(lsock->sk->sk_prot_creator->owner); |
---|
707 | 709 | srv->listener = NULL; |
---|
708 | 710 | spin_unlock_bh(&srv->idr_lock); |
---|
709 | | - sock_release(lsock); |
---|
| 711 | + |
---|
710 | 712 | tipc_topsrv_work_stop(srv); |
---|
| 713 | + sock_release(lsock); |
---|
711 | 714 | idr_destroy(&srv->conn_idr); |
---|
712 | 715 | kfree(srv); |
---|
713 | 716 | } |
---|