Skip to content

Commit a60a2b1

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: reduce active tcp_listen workers
SMC starts a separate tcp_listen worker for every SMC socket in state SMC_LISTEN, and can accept an incoming connection request only, if this worker is really running and waiting in kernel_accept(). But the number of running workers is limited. This patch reworks the listening SMC code and starts a tcp_listen worker after the SYN-ACK handshake on the internal clc-socket only. Suggested-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Reviewed-by: Guvenc Gulce <guvenc@linux.ibm.com> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent b55353e commit a60a2b1

File tree

3 files changed

+36
-11
lines changed

3 files changed

+36
-11
lines changed

net/smc/af_smc.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -940,10 +940,10 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
940940

941941
mutex_lock(&lsmc->clcsock_release_lock);
942942
if (lsmc->clcsock)
943-
rc = kernel_accept(lsmc->clcsock, &new_clcsock, 0);
943+
rc = kernel_accept(lsmc->clcsock, &new_clcsock, SOCK_NONBLOCK);
944944
mutex_unlock(&lsmc->clcsock_release_lock);
945945
lock_sock(lsk);
946-
if (rc < 0)
946+
if (rc < 0 && rc != -EAGAIN)
947947
lsk->sk_err = -rc;
948948
if (rc < 0 || lsk->sk_state == SMC_CLOSED) {
949949
new_sk->sk_prot->unhash(new_sk);
@@ -956,6 +956,10 @@ static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc)
956956
goto out;
957957
}
958958

959+
/* new clcsock has inherited the smc listen-specific sk_data_ready
960+
* function; switch it back to the original sk_data_ready function
961+
*/
962+
new_clcsock->sk->sk_data_ready = lsmc->clcsk_data_ready;
959963
(*new_smc)->clcsock = new_clcsock;
960964
out:
961965
return rc;
@@ -1406,7 +1410,7 @@ static void smc_tcp_listen_work(struct work_struct *work)
14061410
lock_sock(lsk);
14071411
while (lsk->sk_state == SMC_LISTEN) {
14081412
rc = smc_clcsock_accept(lsmc, &new_smc);
1409-
if (rc)
1413+
if (rc) /* clcsock accept queue empty or error */
14101414
goto out;
14111415
if (!new_smc)
14121416
continue;
@@ -1426,7 +1430,23 @@ static void smc_tcp_listen_work(struct work_struct *work)
14261430

14271431
out:
14281432
release_sock(lsk);
1429-
sock_put(&lsmc->sk); /* sock_hold in smc_listen */
1433+
sock_put(&lsmc->sk); /* sock_hold in smc_clcsock_data_ready() */
1434+
}
1435+
1436+
static void smc_clcsock_data_ready(struct sock *listen_clcsock)
1437+
{
1438+
struct smc_sock *lsmc;
1439+
1440+
lsmc = (struct smc_sock *)
1441+
((uintptr_t)listen_clcsock->sk_user_data & ~SK_USER_DATA_NOCOPY);
1442+
if (!lsmc)
1443+
return;
1444+
lsmc->clcsk_data_ready(listen_clcsock);
1445+
if (lsmc->sk.sk_state == SMC_LISTEN) {
1446+
sock_hold(&lsmc->sk); /* sock_put in smc_tcp_listen_work() */
1447+
if (!schedule_work(&lsmc->tcp_listen_work))
1448+
sock_put(&lsmc->sk);
1449+
}
14301450
}
14311451

14321452
static int smc_listen(struct socket *sock, int backlog)
@@ -1455,15 +1475,19 @@ static int smc_listen(struct socket *sock, int backlog)
14551475
if (!smc->use_fallback)
14561476
tcp_sk(smc->clcsock->sk)->syn_smc = 1;
14571477

1478+
/* save original sk_data_ready function and establish
1479+
* smc-specific sk_data_ready function
1480+
*/
1481+
smc->clcsk_data_ready = smc->clcsock->sk->sk_data_ready;
1482+
smc->clcsock->sk->sk_data_ready = smc_clcsock_data_ready;
1483+
smc->clcsock->sk->sk_user_data =
1484+
(void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY);
14581485
rc = kernel_listen(smc->clcsock, backlog);
14591486
if (rc)
14601487
goto out;
14611488
sk->sk_max_ack_backlog = backlog;
14621489
sk->sk_ack_backlog = 0;
14631490
sk->sk_state = SMC_LISTEN;
1464-
sock_hold(sk); /* sock_hold in tcp_listen_worker */
1465-
if (!schedule_work(&smc->tcp_listen_work))
1466-
sock_put(sk);
14671491

14681492
out:
14691493
release_sock(sk);

net/smc/smc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ struct smc_connection {
201201
struct smc_sock { /* smc sock container */
202202
struct sock sk;
203203
struct socket *clcsock; /* internal tcp socket */
204+
void (*clcsk_data_ready)(struct sock *sk);
205+
/* original data_ready fct. **/
204206
struct smc_connection conn; /* smc connection */
205207
struct smc_sock *listen_smc; /* listen parent */
206208
struct work_struct connect_work; /* handle non-blocking connect*/

net/smc/smc_close.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,11 @@ int smc_close_active(struct smc_sock *smc)
208208
break;
209209
case SMC_LISTEN:
210210
sk->sk_state = SMC_CLOSED;
211+
smc->clcsock->sk->sk_data_ready = smc->clcsk_data_ready;
212+
smc->clcsock->sk->sk_user_data = NULL;
211213
sk->sk_state_change(sk); /* wake up accept */
212-
if (smc->clcsock && smc->clcsock->sk) {
214+
if (smc->clcsock && smc->clcsock->sk)
213215
rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR);
214-
/* wake up kernel_accept of smc_tcp_listen_worker */
215-
smc->clcsock->sk->sk_data_ready(smc->clcsock->sk);
216-
}
217216
smc_close_cleanup_listen(sk);
218217
release_sock(sk);
219218
flush_work(&smc->tcp_listen_work);

0 commit comments

Comments
 (0)