mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
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>
This commit is contained in:
parent
1b2c46cdb7
commit
ac31755c7a
|
|
@ -610,6 +610,14 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
|||
response->sge.length,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
/*
|
||||
* Reset timer to the keepalive interval in
|
||||
* order to trigger our next keepalive message.
|
||||
*/
|
||||
info->keep_alive_requested = KEEP_ALIVE_NONE;
|
||||
mod_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->keepalive_interval_msec));
|
||||
|
||||
switch (sc->recv_io.expected) {
|
||||
/* SMBD negotiation response */
|
||||
case SMBDIRECT_EXPECT_NEGOTIATE_REP:
|
||||
|
|
@ -684,11 +692,11 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
|
|||
le32_to_cpu(data_transfer->data_length),
|
||||
le32_to_cpu(data_transfer->remaining_data_length));
|
||||
|
||||
/* Send a KEEP_ALIVE response right away if requested */
|
||||
info->keep_alive_requested = KEEP_ALIVE_NONE;
|
||||
/* Send an immediate response right away if requested */
|
||||
if (le16_to_cpu(data_transfer->flags) &
|
||||
SMBDIRECT_FLAG_RESPONSE_REQUESTED) {
|
||||
info->keep_alive_requested = KEEP_ALIVE_PENDING;
|
||||
log_keep_alive(INFO, "schedule send of immediate response\n");
|
||||
queue_work(info->workqueue, &info->send_immediate_work);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -987,8 +995,17 @@ static int manage_credits_prior_sending(struct smbd_connection *info)
|
|||
*/
|
||||
static int manage_keep_alive_before_sending(struct smbd_connection *info)
|
||||
{
|
||||
struct smbdirect_socket *sc = &info->socket;
|
||||
struct smbdirect_socket_parameters *sp = &sc->parameters;
|
||||
|
||||
if (info->keep_alive_requested == KEEP_ALIVE_PENDING) {
|
||||
info->keep_alive_requested = KEEP_ALIVE_SENT;
|
||||
/*
|
||||
* Now use the keepalive timeout (instead of keepalive interval)
|
||||
* in order to wait for a response
|
||||
*/
|
||||
mod_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->keepalive_timeout_msec));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -999,7 +1016,6 @@ static int smbd_post_send(struct smbd_connection *info,
|
|||
struct smbdirect_send_io *request)
|
||||
{
|
||||
struct smbdirect_socket *sc = &info->socket;
|
||||
struct smbdirect_socket_parameters *sp = &sc->parameters;
|
||||
struct ib_send_wr send_wr;
|
||||
int rc, i;
|
||||
|
||||
|
|
@ -1028,10 +1044,7 @@ static int smbd_post_send(struct smbd_connection *info,
|
|||
log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc);
|
||||
smbd_disconnect_rdma_connection(info);
|
||||
rc = -EAGAIN;
|
||||
} else
|
||||
/* Reset timer for idle connection after packet is sent */
|
||||
mod_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->keepalive_interval_msec));
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1486,12 +1499,18 @@ static void idle_connection_timer(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Now use the keepalive timeout (instead of keepalive interval)
|
||||
* in order to wait for a response
|
||||
*/
|
||||
info->keep_alive_requested = KEEP_ALIVE_PENDING;
|
||||
mod_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->keepalive_timeout_msec));
|
||||
log_keep_alive(INFO, "schedule send of empty idle message\n");
|
||||
queue_work(info->workqueue, &info->send_immediate_work);
|
||||
|
||||
/* Setup the next idle timeout work */
|
||||
queue_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->keepalive_interval_msec));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1881,8 +1900,13 @@ static struct smbd_connection *_smbd_get_connection(
|
|||
|
||||
INIT_WORK(&info->send_immediate_work, send_immediate_empty_message);
|
||||
INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
|
||||
queue_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->keepalive_interval_msec));
|
||||
/*
|
||||
* start with the negotiate timeout and KEEP_ALIVE_PENDING
|
||||
* so that the timer will cause a disconnect.
|
||||
*/
|
||||
info->keep_alive_requested = KEEP_ALIVE_PENDING;
|
||||
mod_delayed_work(info->workqueue, &info->idle_timer_work,
|
||||
msecs_to_jiffies(sp->negotiate_timeout_msec));
|
||||
|
||||
INIT_WORK(&sc->recv_io.posted.refill_work, smbd_post_send_credits);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user