net/smc: rebuild nonblocking connect
The recent poll change may lead to stalls for non-blocking connecting
SMC sockets, since sock_poll_wait is no longer performed on the
internal CLC socket, but on the outer SMC socket. kernel_connect() on
the internal CLC socket returns with -EINPROGRESS, but the wake up
logic does not work in all cases. If the internal CLC socket is still
in state TCP_SYN_SENT when polled, sock_poll_wait() from sock_poll()
does not sleep. It is supposed to sleep till the state of the internal
CLC socket switches to TCP_ESTABLISHED.
This problem triggered a redesign of the SMC nonblocking connect logic.
This patch introduces a connect worker covering all connect steps
followed by a wake up of socket waiters. It allows to get rid of all
delays and locks in smc_poll().
Fixes: c0129a0614
("smc: convert to ->poll_mask")
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
15ecbe94a4
commit
24ac3a08e6
@@ -187,11 +187,19 @@ struct smc_connection {
|
||||
struct work_struct close_work; /* peer sent some closing */
|
||||
};
|
||||
|
||||
struct smc_connect_info {
|
||||
int flags;
|
||||
int alen;
|
||||
struct sockaddr addr;
|
||||
};
|
||||
|
||||
struct smc_sock { /* smc sock container */
|
||||
struct sock sk;
|
||||
struct socket *clcsock; /* internal tcp socket */
|
||||
struct smc_connection conn; /* smc connection */
|
||||
struct smc_sock *listen_smc; /* listen parent */
|
||||
struct smc_connect_info *connect_info; /* connect address & flags */
|
||||
struct work_struct connect_work; /* handle non-blocking connect*/
|
||||
struct work_struct tcp_listen_work;/* handle tcp socket accepts */
|
||||
struct work_struct smc_listen_work;/* prepare new accept socket */
|
||||
struct list_head accept_q; /* sockets to be accepted */
|
||||
|
Reference in New Issue
Block a user