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>
This commit is contained in:
Родитель
35997e3157
Коммит
f662c07058
|
@ -429,36 +429,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
|
|||
* to handle any preventable race conditions, so TIPC will do the same ...
|
||||
*
|
||||
* TIPC sets the returned events as follows:
|
||||
* a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
|
||||
* or if a connection-oriented socket is does not have an active connection
|
||||
* (i.e. a read operation will not block).
|
||||
* b) POLLOUT is set except when a socket's connection has been terminated
|
||||
* (i.e. a write operation will not block).
|
||||
* c) POLLHUP is set when a socket's connection has been terminated.
|
||||
*
|
||||
* IMPORTANT: The fact that a read or write operation will not block does NOT
|
||||
* imply that the operation will succeed!
|
||||
* socket state flags set
|
||||
* ------------ ---------
|
||||
* unconnected no read flags
|
||||
* no write flags
|
||||
*
|
||||
* connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue
|
||||
* no write flags
|
||||
*
|
||||
* connected POLLIN/POLLRDNORM if data in rx queue
|
||||
* POLLOUT if port is not congested
|
||||
*
|
||||
* disconnecting POLLIN/POLLRDNORM/POLLHUP
|
||||
* no write flags
|
||||
*
|
||||
* listening POLLIN if SYN in rx queue
|
||||
* no write flags
|
||||
*
|
||||
* ready POLLIN/POLLRDNORM if data in rx queue
|
||||
* [connectionless] POLLOUT (since port cannot be congested)
|
||||
*
|
||||
* IMPORTANT: The fact that a read or write operation is indicated does NOT
|
||||
* imply that the operation will succeed, merely that it should be performed
|
||||
* and will not block.
|
||||
*/
|
||||
|
||||
static unsigned int poll(struct file *file, struct socket *sock,
|
||||
poll_table *wait)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
u32 mask;
|
||||
u32 mask = 0;
|
||||
|
||||
poll_wait(file, sk_sleep(sk), wait);
|
||||
|
||||
if (!skb_queue_empty(&sk->sk_receive_queue) ||
|
||||
(sock->state == SS_UNCONNECTED) ||
|
||||
(sock->state == SS_DISCONNECTING))
|
||||
mask = (POLLRDNORM | POLLIN);
|
||||
else
|
||||
mask = 0;
|
||||
|
||||
if (sock->state == SS_DISCONNECTING)
|
||||
mask |= POLLHUP;
|
||||
else
|
||||
mask |= POLLOUT;
|
||||
switch ((int)sock->state) {
|
||||
case SS_READY:
|
||||
case SS_CONNECTED:
|
||||
if (!tipc_sk_port(sk)->congested)
|
||||
mask |= POLLOUT;
|
||||
/* fall thru' */
|
||||
case SS_CONNECTING:
|
||||
case SS_LISTENING:
|
||||
if (!skb_queue_empty(&sk->sk_receive_queue))
|
||||
mask |= (POLLIN | POLLRDNORM);
|
||||
break;
|
||||
case SS_DISCONNECTING:
|
||||
mask = (POLLIN | POLLRDNORM | POLLHUP);
|
||||
break;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче