Skip to content

Commit ac31755

Browse files
metze-sambasmfrench
authored andcommitted
smb: client: fix smbdirect keep alive handling to match the documentation
We setup the first timer with the negotiate timeout and set KEEP_ALIVE_PENDING, so that the expired timer disconnects. On every incoming message we need to reset the timer to the keepalive interval (120s). On SMBDIRECT_FLAG_RESPONSE_REQUESTED we need to schedule a response instead of setting KEEP_ALIVE_PENDING. Doing both would mean we would also set SMBDIRECT_FLAG_RESPONSE_REQUESTED in that response. If both ends would do that we'd play ping pong in a busy loop. If we move to KEEP_ALIVE_SENT and send the keepalive request with SMBDIRECT_FLAG_RESPONSE_REQUESTED, we need to setup the timer with keepalive timeout (5s) in order to disconnect if no incoming message reset the timer. The fired timer sets KEEP_ALIVE_PENDING and also setup timer with keepalive timeout (5s) in order to disconnect if no incoming message reset the timer. We do that before queueing the send_immediate_work and have that timer in case we didn't reach the send code that typically sets the timer to keepalive timeout. Cc: Steve French <smfrench@gmail.com> Cc: Tom Talpey <tom@talpey.com> Cc: Long Li <longli@microsoft.com> Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Stefan Metzmacher <metze@samba.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 1b2c46c commit ac31755

File tree

1 file changed

+38
-14
lines changed

1 file changed

+38
-14
lines changed

fs/smb/client/smbdirect.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,14 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
610610
response->sge.length,
611611
DMA_FROM_DEVICE);
612612

613+
/*
614+
* Reset timer to the keepalive interval in
615+
* order to trigger our next keepalive message.
616+
*/
617+
info->keep_alive_requested = KEEP_ALIVE_NONE;
618+
mod_delayed_work(info->workqueue, &info->idle_timer_work,
619+
msecs_to_jiffies(sp->keepalive_interval_msec));
620+
613621
switch (sc->recv_io.expected) {
614622
/* SMBD negotiation response */
615623
case SMBDIRECT_EXPECT_NEGOTIATE_REP:
@@ -684,11 +692,11 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
684692
le32_to_cpu(data_transfer->data_length),
685693
le32_to_cpu(data_transfer->remaining_data_length));
686694

687-
/* Send a KEEP_ALIVE response right away if requested */
688-
info->keep_alive_requested = KEEP_ALIVE_NONE;
695+
/* Send an immediate response right away if requested */
689696
if (le16_to_cpu(data_transfer->flags) &
690697
SMBDIRECT_FLAG_RESPONSE_REQUESTED) {
691-
info->keep_alive_requested = KEEP_ALIVE_PENDING;
698+
log_keep_alive(INFO, "schedule send of immediate response\n");
699+
queue_work(info->workqueue, &info->send_immediate_work);
692700
}
693701

694702
/*
@@ -987,8 +995,17 @@ static int manage_credits_prior_sending(struct smbd_connection *info)
987995
*/
988996
static int manage_keep_alive_before_sending(struct smbd_connection *info)
989997
{
998+
struct smbdirect_socket *sc = &info->socket;
999+
struct smbdirect_socket_parameters *sp = &sc->parameters;
1000+
9901001
if (info->keep_alive_requested == KEEP_ALIVE_PENDING) {
9911002
info->keep_alive_requested = KEEP_ALIVE_SENT;
1003+
/*
1004+
* Now use the keepalive timeout (instead of keepalive interval)
1005+
* in order to wait for a response
1006+
*/
1007+
mod_delayed_work(info->workqueue, &info->idle_timer_work,
1008+
msecs_to_jiffies(sp->keepalive_timeout_msec));
9921009
return 1;
9931010
}
9941011
return 0;
@@ -999,7 +1016,6 @@ static int smbd_post_send(struct smbd_connection *info,
9991016
struct smbdirect_send_io *request)
10001017
{
10011018
struct smbdirect_socket *sc = &info->socket;
1002-
struct smbdirect_socket_parameters *sp = &sc->parameters;
10031019
struct ib_send_wr send_wr;
10041020
int rc, i;
10051021

@@ -1028,10 +1044,7 @@ static int smbd_post_send(struct smbd_connection *info,
10281044
log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
10291045
smbd_disconnect_rdma_connection(info);
10301046
rc = -EAGAIN;
1031-
} else
1032-
/* Reset timer for idle connection after packet is sent */
1033-
mod_delayed_work(info->workqueue, &info->idle_timer_work,
1034-
msecs_to_jiffies(sp->keepalive_interval_msec));
1047+
}
10351048

10361049
return rc;
10371050
}
@@ -1486,12 +1499,18 @@ static void idle_connection_timer(struct work_struct *work)
14861499
return;
14871500
}
14881501

1502+
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
1503+
return;
1504+
1505+
/*
1506+
* Now use the keepalive timeout (instead of keepalive interval)
1507+
* in order to wait for a response
1508+
*/
1509+
info->keep_alive_requested = KEEP_ALIVE_PENDING;
1510+
mod_delayed_work(info->workqueue, &info->idle_timer_work,
1511+
msecs_to_jiffies(sp->keepalive_timeout_msec));
14891512
log_keep_alive(INFO, "schedule send of empty idle message\n");
14901513
queue_work(info->workqueue, &info->send_immediate_work);
1491-
1492-
/* Setup the next idle timeout work */
1493-
queue_delayed_work(info->workqueue, &info->idle_timer_work,
1494-
msecs_to_jiffies(sp->keepalive_interval_msec));
14951514
}
14961515

14971516
/*
@@ -1881,8 +1900,13 @@ static struct smbd_connection *_smbd_get_connection(
18811900

18821901
INIT_WORK(&info->send_immediate_work, send_immediate_empty_message);
18831902
INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
1884-
queue_delayed_work(info->workqueue, &info->idle_timer_work,
1885-
msecs_to_jiffies(sp->keepalive_interval_msec));
1903+
/*
1904+
* start with the negotiate timeout and KEEP_ALIVE_PENDING
1905+
* so that the timer will cause a disconnect.
1906+
*/
1907+
info->keep_alive_requested = KEEP_ALIVE_PENDING;
1908+
mod_delayed_work(info->workqueue, &info->idle_timer_work,
1909+
msecs_to_jiffies(sp->negotiate_timeout_msec));
18861910

18871911
INIT_WORK(&sc->recv_io.posted.refill_work, smbd_post_send_credits);
18881912

0 commit comments

Comments
 (0)