aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-01-16 20:50:05 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-16 22:10:34 -0500
commit3f40504f7ee419eda0068e55e0ee2622e1fce40b (patch)
tree5a73408e3b982fa823210965fcc4277da18663d5 /net/tipc
parent6398e23cdb1d807132c1d3d007d6b1ec87b511af (diff)
tipc: standardize sendmsg routine of connectionless socket
Comparing the behaviour of how to wait for events in TIPC sendmsg() with other stacks, the TIPC implementation might be perceived as different, and sometimes even incorrect. For instance, sk_sleep() and tport->congested variables associated with socket are exposed without socket lock protection while wait_event_interruptible_timeout() accesses them. So standardizing it with similar implementation in other stacks can help us correct these errors which the process of calling sendmsg() cannot be woken up event if an expected event arrive at socket or improperly woken up although the wake condition doesn't match. Signed-off-by: Ying Xue <ying.xue@windriver.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 008f6fdf95c3..3e019737e4b3 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -567,6 +567,31 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
567 return 0; 567 return 0;
568} 568}
569 569
570static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
571{
572 struct sock *sk = sock->sk;
573 struct tipc_port *tport = tipc_sk_port(sk);
574 DEFINE_WAIT(wait);
575 int done;
576
577 do {
578 int err = sock_error(sk);
579 if (err)
580 return err;
581 if (sock->state == SS_DISCONNECTING)
582 return -EPIPE;
583 if (!*timeo_p)
584 return -EAGAIN;
585 if (signal_pending(current))
586 return sock_intr_errno(*timeo_p);
587
588 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
589 done = sk_wait_event(sk, timeo_p, !tport->congested);
590 finish_wait(sk_sleep(sk), &wait);
591 } while (!done);
592 return 0;
593}
594
570/** 595/**
571 * send_msg - send message in connectionless manner 596 * send_msg - send message in connectionless manner
572 * @iocb: if NULL, indicates that socket lock is already held 597 * @iocb: if NULL, indicates that socket lock is already held
@@ -588,7 +613,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
588 struct tipc_port *tport = tipc_sk_port(sk); 613 struct tipc_port *tport = tipc_sk_port(sk);
589 struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; 614 struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
590 int needs_conn; 615 int needs_conn;
591 long timeout_val; 616 long timeo;
592 int res = -EINVAL; 617 int res = -EINVAL;
593 618
594 if (unlikely(!dest)) 619 if (unlikely(!dest))
@@ -625,8 +650,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
625 reject_rx_queue(sk); 650 reject_rx_queue(sk);
626 } 651 }
627 652
628 timeout_val = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); 653 timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT);
629
630 do { 654 do {
631 if (dest->addrtype == TIPC_ADDR_NAME) { 655 if (dest->addrtype == TIPC_ADDR_NAME) {
632 res = dest_name_check(dest, m); 656 res = dest_name_check(dest, m);
@@ -660,14 +684,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock,
660 sock->state = SS_CONNECTING; 684 sock->state = SS_CONNECTING;
661 break; 685 break;
662 } 686 }
663 if (timeout_val <= 0L) { 687 res = tipc_wait_for_sndmsg(sock, &timeo);
664 res = timeout_val ? timeout_val : -EWOULDBLOCK; 688 if (res)
665 break; 689 break;
666 }
667 release_sock(sk);
668 timeout_val = wait_event_interruptible_timeout(*sk_sleep(sk),
669 !tport->congested, timeout_val);
670 lock_sock(sk);
671 } while (1); 690 } while (1);
672 691
673exit: 692exit: