Commit be6f42fa authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French

ksmbd: don't terminate inactive sessions after a few seconds

Steve reported that inactive sessions are terminated after a few
seconds. ksmbd terminate when receiving -EAGAIN error from
kernel_recvmsg(). -EAGAIN means there is no data available in timeout.
So ksmbd should keep connection with unlimited retries instead of
terminating inactive sessions.

Cc: stable@vger.kernel.org
Reported-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2624b445
......@@ -298,7 +298,7 @@ int ksmbd_conn_handler_loop(void *p)
kvfree(conn->request_buf);
conn->request_buf = NULL;
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
if (size != sizeof(hdr_buf))
break;
......@@ -344,7 +344,7 @@ int ksmbd_conn_handler_loop(void *p)
* We already read 4 bytes to find out PDU size, now
* read in PDU
*/
size = t->ops->read(t, conn->request_buf + 4, pdu_size);
size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
if (size < 0) {
pr_err("sock_read failed: %d\n", size);
break;
......
......@@ -114,7 +114,8 @@ struct ksmbd_transport_ops {
int (*prepare)(struct ksmbd_transport *t);
void (*disconnect)(struct ksmbd_transport *t);
void (*shutdown)(struct ksmbd_transport *t);
int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
int (*read)(struct ksmbd_transport *t, char *buf,
unsigned int size, int max_retries);
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
int size, bool need_invalidate_rkey,
unsigned int remote_key);
......
......@@ -670,7 +670,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
}
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
unsigned int size)
unsigned int size, int unused)
{
struct smb_direct_recvmsg *recvmsg;
struct smb_direct_data_transfer *data_transfer;
......
......@@ -291,16 +291,18 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
/**
* ksmbd_tcp_readv() - read data from socket in given iovec
* @t: TCP transport instance
* @iov_orig: base IO vector
* @nr_segs: number of segments in base iov
* @to_read: number of bytes to read from socket
* @t: TCP transport instance
* @iov_orig: base IO vector
* @nr_segs: number of segments in base iov
* @to_read: number of bytes to read from socket
* @max_retries: maximum retry count
*
* Return: on success return number of bytes read from socket,
* otherwise return error number
*/
static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
unsigned int nr_segs, unsigned int to_read)
unsigned int nr_segs, unsigned int to_read,
int max_retries)
{
int length = 0;
int total_read;
......@@ -308,7 +310,6 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
struct msghdr ksmbd_msg;
struct kvec *iov;
struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
int max_retry = 2;
iov = get_conn_iovec(t, nr_segs);
if (!iov)
......@@ -335,14 +336,23 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
} else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
total_read = -EAGAIN;
break;
} else if ((length == -ERESTARTSYS || length == -EAGAIN) &&
max_retry) {
} else if (length == -ERESTARTSYS || length == -EAGAIN) {
/*
* If max_retries is negative, Allow unlimited
* retries to keep connection with inactive sessions.
*/
if (max_retries == 0) {
total_read = length;
break;
} else if (max_retries > 0) {
max_retries--;
}
usleep_range(1000, 2000);
length = 0;
max_retry--;
continue;
} else if (length <= 0) {
total_read = -EAGAIN;
total_read = length;
break;
}
}
......@@ -358,14 +368,15 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
* Return: on success return number of bytes read from socket,
* otherwise return error number
*/
static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf, unsigned int to_read)
static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
unsigned int to_read, int max_retries)
{
struct kvec iov;
iov.iov_base = buf;
iov.iov_len = to_read;
return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read);
return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
}
static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment