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

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
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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;
+23 −12
Original line number Diff line number Diff line
@@ -295,12 +295,14 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
 * @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,