diff options
author | Allan Stephens <allan.stephens@windriver.com> | 2010-08-17 07:00:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-08-17 20:31:53 -0400 |
commit | f662c07058f7e6365ae65080d772f9122f6f50a9 (patch) | |
tree | 17a8ad3e5e432998d42b25891569f17025cf2b41 /net/tipc/socket.c | |
parent | 35997e3157eba16c6124d440bdf9272087129b2a (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/socket.c')
-rw-r--r-- | net/tipc/socket.c | 61 |
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 | ||
443 | static unsigned int poll(struct file *file, struct socket *sock, | 458 | static 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 | } |