diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 83 |
1 files changed, 53 insertions, 30 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 66e889ba48f..33217fc3d69 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -64,6 +64,7 @@ struct tipc_sock { | |||
64 | struct sock sk; | 64 | struct sock sk; |
65 | struct tipc_port *p; | 65 | struct tipc_port *p; |
66 | struct tipc_portid peer_name; | 66 | struct tipc_portid peer_name; |
67 | long conn_timeout; | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) | 70 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) |
@@ -240,9 +241,9 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, | |||
240 | sock->state = state; | 241 | sock->state = state; |
241 | 242 | ||
242 | sock_init_data(sock, sk); | 243 | sock_init_data(sock, sk); |
243 | sk->sk_rcvtimeo = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT); | ||
244 | sk->sk_backlog_rcv = backlog_rcv; | 244 | sk->sk_backlog_rcv = backlog_rcv; |
245 | tipc_sk(sk)->p = tp_ptr; | 245 | tipc_sk(sk)->p = tp_ptr; |
246 | tipc_sk(sk)->conn_timeout = msecs_to_jiffies(CONN_TIMEOUT_DEFAULT); | ||
246 | 247 | ||
247 | spin_unlock_bh(tp_ptr->lock); | 248 | spin_unlock_bh(tp_ptr->lock); |
248 | 249 | ||
@@ -429,36 +430,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, | |||
429 | * to handle any preventable race conditions, so TIPC will do the same ... | 430 | * to handle any preventable race conditions, so TIPC will do the same ... |
430 | * | 431 | * |
431 | * TIPC sets the returned events as follows: | 432 | * TIPC sets the returned events as follows: |
432 | * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty | 433 | * |
433 | * or if a connection-oriented socket is does not have an active connection | 434 | * socket state flags set |
434 | * (i.e. a read operation will not block). | 435 | * ------------ --------- |
435 | * b) POLLOUT is set except when a socket's connection has been terminated | 436 | * unconnected no read flags |
436 | * (i.e. a write operation will not block). | 437 | * no write flags |
437 | * c) POLLHUP is set when a socket's connection has been terminated. | 438 | * |
438 | * | 439 | * connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue |
439 | * IMPORTANT: The fact that a read or write operation will not block does NOT | 440 | * no write flags |
440 | * imply that the operation will succeed! | 441 | * |
442 | * connected POLLIN/POLLRDNORM if data in rx queue | ||
443 | * POLLOUT if port is not congested | ||
444 | * | ||
445 | * disconnecting POLLIN/POLLRDNORM/POLLHUP | ||
446 | * no write flags | ||
447 | * | ||
448 | * listening POLLIN if SYN in rx queue | ||
449 | * no write flags | ||
450 | * | ||
451 | * ready POLLIN/POLLRDNORM if data in rx queue | ||
452 | * [connectionless] POLLOUT (since port cannot be congested) | ||
453 | * | ||
454 | * IMPORTANT: The fact that a read or write operation is indicated does NOT | ||
455 | * imply that the operation will succeed, merely that it should be performed | ||
456 | * and will not block. | ||
441 | */ | 457 | */ |
442 | 458 | ||
443 | static unsigned int poll(struct file *file, struct socket *sock, | 459 | static unsigned int poll(struct file *file, struct socket *sock, |
444 | poll_table *wait) | 460 | poll_table *wait) |
445 | { | 461 | { |
446 | struct sock *sk = sock->sk; | 462 | struct sock *sk = sock->sk; |
447 | u32 mask; | 463 | u32 mask = 0; |
448 | 464 | ||
449 | poll_wait(file, sk_sleep(sk), wait); | 465 | poll_wait(file, sk_sleep(sk), wait); |
450 | 466 | ||
451 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 467 | switch ((int)sock->state) { |
452 | (sock->state == SS_UNCONNECTED) || | 468 | case SS_READY: |
453 | (sock->state == SS_DISCONNECTING)) | 469 | case SS_CONNECTED: |
454 | mask = (POLLRDNORM | POLLIN); | 470 | if (!tipc_sk_port(sk)->congested) |
455 | else | 471 | mask |= POLLOUT; |
456 | mask = 0; | 472 | /* fall thru' */ |
457 | 473 | case SS_CONNECTING: | |
458 | if (sock->state == SS_DISCONNECTING) | 474 | case SS_LISTENING: |
459 | mask |= POLLHUP; | 475 | if (!skb_queue_empty(&sk->sk_receive_queue)) |
460 | else | 476 | mask |= (POLLIN | POLLRDNORM); |
461 | mask |= POLLOUT; | 477 | break; |
478 | case SS_DISCONNECTING: | ||
479 | mask = (POLLIN | POLLRDNORM | POLLHUP); | ||
480 | break; | ||
481 | } | ||
462 | 482 | ||
463 | return mask; | 483 | return mask; |
464 | } | 484 | } |
@@ -1026,9 +1046,8 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
1026 | struct sk_buff *buf; | 1046 | struct sk_buff *buf; |
1027 | struct tipc_msg *msg; | 1047 | struct tipc_msg *msg; |
1028 | unsigned int sz; | 1048 | unsigned int sz; |
1029 | int sz_to_copy; | 1049 | int sz_to_copy, target, needed; |
1030 | int sz_copied = 0; | 1050 | int sz_copied = 0; |
1031 | int needed; | ||
1032 | char __user *crs = m->msg_iov->iov_base; | 1051 | char __user *crs = m->msg_iov->iov_base; |
1033 | unsigned char *buf_crs; | 1052 | unsigned char *buf_crs; |
1034 | u32 err; | 1053 | u32 err; |
@@ -1050,6 +1069,8 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, | |||
1050 | goto exit; | 1069 | goto exit; |
1051 | } | 1070 | } |
1052 | 1071 | ||
1072 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); | ||
1073 | |||
1053 | restart: | 1074 | restart: |
1054 | 1075 | ||
1055 | /* Look for a message in receive queue; wait if necessary */ | 1076 | /* Look for a message in receive queue; wait if necessary */ |
@@ -1138,7 +1159,7 @@ restart: | |||
1138 | 1159 | ||
1139 | if ((sz_copied < buf_len) && /* didn't get all requested data */ | 1160 | if ((sz_copied < buf_len) && /* didn't get all requested data */ |
1140 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1161 | (!skb_queue_empty(&sk->sk_receive_queue) || |
1141 | (flags & MSG_WAITALL)) && /* and more is ready or required */ | 1162 | (sz_copied < target)) && /* and more is ready or required */ |
1142 | (!(flags & MSG_PEEK)) && /* and aren't just peeking at data */ | 1163 | (!(flags & MSG_PEEK)) && /* and aren't just peeking at data */ |
1143 | (!err)) /* and haven't reached a FIN */ | 1164 | (!err)) /* and haven't reached a FIN */ |
1144 | goto restart; | 1165 | goto restart; |
@@ -1174,7 +1195,7 @@ static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base) | |||
1174 | if (msg_connected(msg)) | 1195 | if (msg_connected(msg)) |
1175 | threshold *= 4; | 1196 | threshold *= 4; |
1176 | 1197 | ||
1177 | return (queue_size >= threshold); | 1198 | return queue_size >= threshold; |
1178 | } | 1199 | } |
1179 | 1200 | ||
1180 | /** | 1201 | /** |
@@ -1365,6 +1386,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1365 | struct msghdr m = {NULL,}; | 1386 | struct msghdr m = {NULL,}; |
1366 | struct sk_buff *buf; | 1387 | struct sk_buff *buf; |
1367 | struct tipc_msg *msg; | 1388 | struct tipc_msg *msg; |
1389 | long timeout; | ||
1368 | int res; | 1390 | int res; |
1369 | 1391 | ||
1370 | lock_sock(sk); | 1392 | lock_sock(sk); |
@@ -1379,7 +1401,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1379 | /* For now, TIPC does not support the non-blocking form of connect() */ | 1401 | /* For now, TIPC does not support the non-blocking form of connect() */ |
1380 | 1402 | ||
1381 | if (flags & O_NONBLOCK) { | 1403 | if (flags & O_NONBLOCK) { |
1382 | res = -EWOULDBLOCK; | 1404 | res = -EOPNOTSUPP; |
1383 | goto exit; | 1405 | goto exit; |
1384 | } | 1406 | } |
1385 | 1407 | ||
@@ -1425,11 +1447,12 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
1425 | 1447 | ||
1426 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ | 1448 | /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */ |
1427 | 1449 | ||
1450 | timeout = tipc_sk(sk)->conn_timeout; | ||
1428 | release_sock(sk); | 1451 | release_sock(sk); |
1429 | res = wait_event_interruptible_timeout(*sk_sleep(sk), | 1452 | res = wait_event_interruptible_timeout(*sk_sleep(sk), |
1430 | (!skb_queue_empty(&sk->sk_receive_queue) || | 1453 | (!skb_queue_empty(&sk->sk_receive_queue) || |
1431 | (sock->state != SS_CONNECTING)), | 1454 | (sock->state != SS_CONNECTING)), |
1432 | sk->sk_rcvtimeo); | 1455 | timeout ? timeout : MAX_SCHEDULE_TIMEOUT); |
1433 | lock_sock(sk); | 1456 | lock_sock(sk); |
1434 | 1457 | ||
1435 | if (res > 0) { | 1458 | if (res > 0) { |
@@ -1692,7 +1715,7 @@ static int setsockopt(struct socket *sock, | |||
1692 | res = tipc_set_portunreturnable(tport->ref, value); | 1715 | res = tipc_set_portunreturnable(tport->ref, value); |
1693 | break; | 1716 | break; |
1694 | case TIPC_CONN_TIMEOUT: | 1717 | case TIPC_CONN_TIMEOUT: |
1695 | sk->sk_rcvtimeo = msecs_to_jiffies(value); | 1718 | tipc_sk(sk)->conn_timeout = msecs_to_jiffies(value); |
1696 | /* no need to set "res", since already 0 at this point */ | 1719 | /* no need to set "res", since already 0 at this point */ |
1697 | break; | 1720 | break; |
1698 | default: | 1721 | default: |
@@ -1747,7 +1770,7 @@ static int getsockopt(struct socket *sock, | |||
1747 | res = tipc_portunreturnable(tport->ref, &value); | 1770 | res = tipc_portunreturnable(tport->ref, &value); |
1748 | break; | 1771 | break; |
1749 | case TIPC_CONN_TIMEOUT: | 1772 | case TIPC_CONN_TIMEOUT: |
1750 | value = jiffies_to_msecs(sk->sk_rcvtimeo); | 1773 | value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); |
1751 | /* no need to set "res", since already 0 at this point */ | 1774 | /* no need to set "res", since already 0 at this point */ |
1752 | break; | 1775 | break; |
1753 | case TIPC_NODE_RECVQ_DEPTH: | 1776 | case TIPC_NODE_RECVQ_DEPTH: |