--- /dev/null
+From ef68e831840c40c7d01b328b3c0f5d8c4796c232 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Fri, 18 Jan 2019 17:25:36 -0800
+Subject: CIFS: Do not reconnect TCP session in add_credits()
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit ef68e831840c40c7d01b328b3c0f5d8c4796c232 upstream.
+
+When executing add_credits() we currently call cifs_reconnect()
+if the number of credits is zero and there are no requests in
+flight. In this case we may call cifs_reconnect() recursively
+twice and cause memory corruption given the following sequence
+of functions:
+
+mid1.callback() -> add_credits() -> cifs_reconnect() ->
+-> mid2.callback() -> add_credits() -> cifs_reconnect().
+
+Fix this by avoiding to call cifs_reconnect() in add_credits()
+and checking for zero credits in the demultiplex thread.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/connect.c | 21 +++++++++++++++++++++
+ fs/cifs/smb2ops.c | 32 +++++++++++++++++++++++++-------
+ 2 files changed, 46 insertions(+), 7 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -533,6 +533,21 @@ server_unresponsive(struct TCP_Server_In
+ return false;
+ }
+
++static inline bool
++zero_credits(struct TCP_Server_Info *server)
++{
++ int val;
++
++ spin_lock(&server->req_lock);
++ val = server->credits + server->echo_credits + server->oplock_credits;
++ if (server->in_flight == 0 && val == 0) {
++ spin_unlock(&server->req_lock);
++ return true;
++ }
++ spin_unlock(&server->req_lock);
++ return false;
++}
++
+ static int
+ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
+ {
+@@ -545,6 +560,12 @@ cifs_readv_from_socket(struct TCP_Server
+ for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
+ try_to_freeze();
+
++ /* reconnect if no credits and no requests in flight */
++ if (zero_credits(server)) {
++ cifs_reconnect(server);
++ return -ECONNABORTED;
++ }
++
+ if (server_unresponsive(server))
+ return -ECONNABORTED;
+ if (cifs_rdma_enabled(server) && server->smbd_conn)
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -34,6 +34,7 @@
+ #include "cifs_ioctl.h"
+ #include "smbdirect.h"
+
++/* Change credits for different ops and return the total number of credits */
+ static int
+ change_conf(struct TCP_Server_Info *server)
+ {
+@@ -41,17 +42,15 @@ change_conf(struct TCP_Server_Info *serv
+ server->oplock_credits = server->echo_credits = 0;
+ switch (server->credits) {
+ case 0:
+- return -1;
++ return 0;
+ case 1:
+ server->echoes = false;
+ server->oplocks = false;
+- cifs_dbg(VFS, "disabling echoes and oplocks\n");
+ break;
+ case 2:
+ server->echoes = true;
+ server->oplocks = false;
+ server->echo_credits = 1;
+- cifs_dbg(FYI, "disabling oplocks\n");
+ break;
+ default:
+ server->echoes = true;
+@@ -64,14 +63,15 @@ change_conf(struct TCP_Server_Info *serv
+ server->echo_credits = 1;
+ }
+ server->credits -= server->echo_credits + server->oplock_credits;
+- return 0;
++ return server->credits + server->echo_credits + server->oplock_credits;
+ }
+
+ static void
+ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
+ const int optype)
+ {
+- int *val, rc = 0;
++ int *val, rc = -1;
++
+ spin_lock(&server->req_lock);
+ val = server->ops->get_credits_field(server, optype);
+ *val += add;
+@@ -95,8 +95,26 @@ smb2_add_credits(struct TCP_Server_Info
+ }
+ spin_unlock(&server->req_lock);
+ wake_up(&server->request_q);
+- if (rc)
+- cifs_reconnect(server);
++
++ if (server->tcpStatus == CifsNeedReconnect)
++ return;
++
++ switch (rc) {
++ case -1:
++ /* change_conf hasn't been executed */
++ break;
++ case 0:
++ cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
++ break;
++ case 1:
++ cifs_dbg(VFS, "disabling echoes and oplocks\n");
++ break;
++ case 2:
++ cifs_dbg(FYI, "disabling oplocks\n");
++ break;
++ default:
++ cifs_dbg(FYI, "add %u credits total=%d\n", add, rc);
++ }
+ }
+
+ static void
--- /dev/null
+From ec678eae746dd25766a61c4095e2b649d3b20b09 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Fri, 18 Jan 2019 15:38:11 -0800
+Subject: CIFS: Fix credit calculation for encrypted reads with errors
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit ec678eae746dd25766a61c4095e2b649d3b20b09 upstream.
+
+We do need to account for credits received in error responses
+to read requests on encrypted sessions.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -2901,11 +2901,23 @@ handle_read_data(struct TCP_Server_Info
+ server->ops->is_status_pending(buf, server, 0))
+ return -1;
+
+- rdata->result = server->ops->map_error(buf, false);
++ /* set up first two iov to get credits */
++ rdata->iov[0].iov_base = buf;
++ rdata->iov[0].iov_len = 4;
++ rdata->iov[1].iov_base = buf + 4;
++ rdata->iov[1].iov_len =
++ min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4;
++ cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
++ rdata->iov[0].iov_base, rdata->iov[0].iov_len);
++ cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
++ rdata->iov[1].iov_base, rdata->iov[1].iov_len);
++
++ rdata->result = server->ops->map_error(buf, true);
+ if (rdata->result != 0) {
+ cifs_dbg(FYI, "%s: server returned error %d\n",
+ __func__, rdata->result);
+- dequeue_mid(mid, rdata->result);
++ /* normal error on read response */
++ dequeue_mid(mid, false);
+ return 0;
+ }
+
+@@ -2978,14 +2990,6 @@ handle_read_data(struct TCP_Server_Info
+ return 0;
+ }
+
+- /* set up first iov for signature check */
+- rdata->iov[0].iov_base = buf;
+- rdata->iov[0].iov_len = 4;
+- rdata->iov[1].iov_base = buf + 4;
+- rdata->iov[1].iov_len = server->vals->read_rsp_size - 4;
+- cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+- rdata->iov[0].iov_base, server->vals->read_rsp_size);
+-
+ length = rdata->copy_into_pages(server, rdata, &iter);
+
+ kfree(bvec);
--- /dev/null
+From 8004c78c68e894e4fd5ac3c22cc22eb7dc24cabc Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Thu, 17 Jan 2019 15:29:26 -0800
+Subject: CIFS: Fix credits calculations for reads with errors
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit 8004c78c68e894e4fd5ac3c22cc22eb7dc24cabc upstream.
+
+Currently we mark MID as malformed if we get an error from server
+in a read response. This leads to not properly processing credits
+in the readv callback. Fix this by marking such a response as
+normal received response and process it appropriately.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifssmb.c | 35 +++++++++++++++++++++++------------
+ 1 file changed, 23 insertions(+), 12 deletions(-)
+
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -1458,18 +1458,26 @@ cifs_discard_remaining_data(struct TCP_S
+ }
+
+ static int
+-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
++__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
++ bool malformed)
+ {
+ int length;
+- struct cifs_readdata *rdata = mid->callback_data;
+
+ length = cifs_discard_remaining_data(server);
+- dequeue_mid(mid, rdata->result);
++ dequeue_mid(mid, malformed);
+ mid->resp_buf = server->smallbuf;
+ server->smallbuf = NULL;
+ return length;
+ }
+
++static int
++cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
++{
++ struct cifs_readdata *rdata = mid->callback_data;
++
++ return __cifs_readv_discard(server, mid, rdata->result);
++}
++
+ int
+ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+ {
+@@ -1511,12 +1519,23 @@ cifs_readv_receive(struct TCP_Server_Inf
+ return -1;
+ }
+
++ /* set up first two iov for signature check and to get credits */
++ rdata->iov[0].iov_base = buf;
++ rdata->iov[0].iov_len = 4;
++ rdata->iov[1].iov_base = buf + 4;
++ rdata->iov[1].iov_len = server->total_read - 4;
++ cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
++ rdata->iov[0].iov_base, rdata->iov[0].iov_len);
++ cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
++ rdata->iov[1].iov_base, rdata->iov[1].iov_len);
++
+ /* Was the SMB read successful? */
+ rdata->result = server->ops->map_error(buf, false);
+ if (rdata->result != 0) {
+ cifs_dbg(FYI, "%s: server returned error %d\n",
+ __func__, rdata->result);
+- return cifs_readv_discard(server, mid);
++ /* normal error on read response */
++ return __cifs_readv_discard(server, mid, false);
+ }
+
+ /* Is there enough to get to the rest of the READ_RSP header? */
+@@ -1560,14 +1579,6 @@ cifs_readv_receive(struct TCP_Server_Inf
+ server->total_read += length;
+ }
+
+- /* set up first iov for signature check */
+- rdata->iov[0].iov_base = buf;
+- rdata->iov[0].iov_len = 4;
+- rdata->iov[1].iov_base = buf + 4;
+- rdata->iov[1].iov_len = server->total_read - 4;
+- cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
+- rdata->iov[0].iov_base, server->total_read);
+-
+ /* how much data is in the response? */
+ #ifdef CONFIG_CIFS_SMB_DIRECT
+ use_rdma_mr = rdata->mr;
--- /dev/null
+From acc58d0bab55a50e02c25f00bd6a210ee121595f Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Thu, 17 Jan 2019 08:21:24 -0800
+Subject: CIFS: Fix possible hang during async MTU reads and writes
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit acc58d0bab55a50e02c25f00bd6a210ee121595f upstream.
+
+When doing MTU i/o we need to leave some credits for
+possible reopen requests and other operations happening
+in parallel. Currently we leave 1 credit which is not
+enough even for reopen only: we need at least 2 credits
+if durable handle reconnect fails. Also there may be
+other operations at the same time including compounding
+ones which require 3 credits at a time each. Fix this
+by leaving 8 credits which is big enough to cover most
+scenarios.
+
+Was able to reproduce this when server was configured
+to give out fewer credits than usual.
+
+The proper fix would be to reconnect a file handle first
+and then obtain credits for an MTU request but this leads
+to bigger code changes and should happen in other patches.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -154,14 +154,14 @@ smb2_wait_mtu_credits(struct TCP_Server_
+
+ scredits = server->credits;
+ /* can deadlock with reopen */
+- if (scredits == 1) {
++ if (scredits <= 8) {
+ *num = SMB2_MAX_BUFFER_SIZE;
+ *credits = 0;
+ break;
+ }
+
+- /* leave one credit for a possible reopen */
+- scredits--;
++ /* leave some credits for reopen and other ops */
++ scredits -= 8;
+ *num = min_t(unsigned int, size,
+ scredits * SMB2_MAX_BUFFER_SIZE);
+
hv_balloon-avoid-touching-uninitialized-struct-page-during-tail-onlining.patch
drivers-hv-vmbus-check-for-ring-when-getting-debug-info.patch
vgacon-unconfuse-vc_origin-when-using-soft-scrollback.patch
+cifs-fix-possible-hang-during-async-mtu-reads-and-writes.patch
+cifs-fix-credits-calculations-for-reads-with-errors.patch
+cifs-fix-credit-calculation-for-encrypted-reads-with-errors.patch
+cifs-do-not-reconnect-tcp-session-in-add_credits.patch
+smb3-add-credits-we-receive-from-oplock-break-pdus.patch
--- /dev/null
+From 2e5700bdde438ed708b36d8acd0398dc73cbf759 Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Wed, 23 Jan 2019 16:20:38 +1000
+Subject: smb3: add credits we receive from oplock/break PDUs
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+commit 2e5700bdde438ed708b36d8acd0398dc73cbf759 upstream.
+
+Otherwise we gradually leak credits leading to potential
+hung session.
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2misc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/fs/cifs/smb2misc.c
++++ b/fs/cifs/smb2misc.c
+@@ -648,6 +648,13 @@ smb2_is_valid_oplock_break(char *buffer,
+ if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
+ return false;
+
++ if (rsp->sync_hdr.CreditRequest) {
++ spin_lock(&server->req_lock);
++ server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest);
++ spin_unlock(&server->req_lock);
++ wake_up(&server->request_q);
++ }
++
+ if (rsp->StructureSize !=
+ smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
+ if (le16_to_cpu(rsp->StructureSize) == 44)