aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2010-08-17 07:00:06 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-17 20:31:53 -0400
commitf662c07058f7e6365ae65080d772f9122f6f50a9 (patch)
tree17a8ad3e5e432998d42b25891569f17025cf2b41 /net/tipc
parent35997e3157eba16c6124d440bdf9272087129b2a (diff)
tipc: correct problems with misleading flags returned using poll()
Prevent TIPC from incorrectly setting returned flags to poll() in the following cases: - an unconnected socket no longer indicates that it is always readable - an unconnected, connecting, or listening socket no longer indicates that it is always writable Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/socket.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index b89c7b1a0d09..7b81fdd4f6d6 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -429,36 +429,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
429 * to handle any preventable race conditions, so TIPC will do the same ... 429 * to handle any preventable race conditions, so TIPC will do the same ...
430 * 430 *
431 * TIPC sets the returned events as follows: 431 * TIPC sets the returned events as follows:
432 * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty 432 *
433 * or if a connection-oriented socket is does not have an active connection 433 * socket state flags set
434 * (i.e. a read operation will not block). 434 * ------------ ---------
435 * b) POLLOUT is set except when a socket's connection has been terminated 435 * unconnected no read flags
436 * (i.e. a write operation will not block). 436 * no write flags
437 * c) POLLHUP is set when a socket's connection has been terminated. 437 *
438 * 438 * connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue
439 * IMPORTANT: The fact that a read or write operation will not block does NOT 439 * no write flags
440 * imply that the operation will succeed! 440 *
441 * connected POLLIN/POLLRDNORM if data in rx queue
442 * POLLOUT if port is not congested
443 *
444 * disconnecting POLLIN/POLLRDNORM/POLLHUP
445 * no write flags
446 *
447 * listening POLLIN if SYN in rx queue
448 * no write flags
449 *
450 * ready POLLIN/POLLRDNORM if data in rx queue
451 * [connectionless] POLLOUT (since port cannot be congested)
452 *
453 * IMPORTANT: The fact that a read or write operation is indicated does NOT
454 * imply that the operation will succeed, merely that it should be performed
455 * and will not block.
441 */ 456 */
442 457
443static unsigned int poll(struct file *file, struct socket *sock, 458static unsigned int poll(struct file *file, struct socket *sock,
444 poll_table *wait) 459 poll_table *wait)
445{ 460{
446 struct sock *sk = sock->sk; 461 struct sock *sk = sock->sk;
447 u32 mask; 462 u32 mask = 0;
448 463
449 poll_wait(file, sk_sleep(sk), wait); 464 poll_wait(file, sk_sleep(sk), wait);
450 465
451 if (!skb_queue_empty(&sk->sk_receive_queue) || 466 switch ((int)sock->state) {
452 (sock->state == SS_UNCONNECTED) || 467 case SS_READY:
453 (sock->state == SS_DISCONNECTING)) 468 case SS_CONNECTED:
454 mask = (POLLRDNORM | POLLIN); 469 if (!tipc_sk_port(sk)->congested)
455 else 470 mask |= POLLOUT;
456 mask = 0; 471 /* fall thru' */
457 472 case SS_CONNECTING:
458 if (sock->state == SS_DISCONNECTING) 473 case SS_LISTENING:
459 mask |= POLLHUP; 474 if (!skb_queue_empty(&sk->sk_receive_queue))
460 else 475 mask |= (POLLIN | POLLRDNORM);
461 mask |= POLLOUT; 476 break;
477 case SS_DISCONNECTING:
478 mask = (POLLIN | POLLRDNORM | POLLHUP);
479 break;
480 }
462 481
463 return mask; 482 return mask;
464} 483}