Home Home > GIT Browse > stable
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2019-01-18 07:53:27 +0100
committerJiri Slaby <jslaby@suse.cz>2019-01-18 07:53:32 +0100
commite3c0972c599451202819b37c21f50153e75dff9d (patch)
treed98a958571da7a2af65e658a9be47b4f83b4a4df
parent27e0f9d0b85b961f0d09c19f1ab102c44fa331f9 (diff)
CIFS: Fix credit computation for compounded requests
-rw-r--r--patches.kernel.org/4.20.3-015-CIFS-Fix-credit-computation-for-compounded-req.patch143
-rw-r--r--series.conf1
2 files changed, 144 insertions, 0 deletions
diff --git a/patches.kernel.org/4.20.3-015-CIFS-Fix-credit-computation-for-compounded-req.patch b/patches.kernel.org/4.20.3-015-CIFS-Fix-credit-computation-for-compounded-req.patch
new file mode 100644
index 0000000000..56ebcfe6af
--- /dev/null
+++ b/patches.kernel.org/4.20.3-015-CIFS-Fix-credit-computation-for-compounded-req.patch
@@ -0,0 +1,143 @@
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Sat, 22 Dec 2018 12:40:05 -0800
+Subject: [PATCH] CIFS: Fix credit computation for compounded requests
+References: bnc#1012628
+Patch-mainline: 4.20.3
+Git-commit: 8544f4aa9dd19a04d1244dae10feecc813ccf175
+
+commit 8544f4aa9dd19a04d1244dae10feecc813ccf175 upstream.
+
+In SMB3 protocol every part of the compound chain consumes credits
+individually, so we need to call wait_for_free_credits() for each
+of the PDUs in the chain. If an operation is interrupted, we must
+ensure we return all credits taken from the server structure back.
+
+Without this patch server can sometimes disconnect the session
+due to credit mismatches, especially when first operation(s)
+are large writes.
+
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+---
+ fs/cifs/transport.c | 59 +++++++++++++++++++++++++++++++--------------
+ 1 file changed, 41 insertions(+), 18 deletions(-)
+
+diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
+index ea59eb01a49b..d51064c1ba42 100644
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -793,7 +793,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ int i, j, rc = 0;
+ int timeout, optype;
+ struct mid_q_entry *midQ[MAX_COMPOUND];
+- unsigned int credits = 0;
++ bool cancelled_mid[MAX_COMPOUND] = {false};
++ unsigned int credits[MAX_COMPOUND] = {0};
+ char *buf;
+
+ timeout = flags & CIFS_TIMEOUT_MASK;
+@@ -811,13 +812,31 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ return -ENOENT;
+
+ /*
+- * Ensure that we do not send more than 50 overlapping requests
+- * to the same server. We may make this configurable later or
+- * use ses->maxReq.
++ * Ensure we obtain 1 credit per request in the compound chain.
++ * It can be optimized further by waiting for all the credits
++ * at once but this can wait long enough if we don't have enough
++ * credits due to some heavy operations in progress or the server
++ * not granting us much, so a fallback to the current approach is
++ * needed anyway.
+ */
+- rc = wait_for_free_request(ses->server, timeout, optype);
+- if (rc)
+- return rc;
++ for (i = 0; i < num_rqst; i++) {
++ rc = wait_for_free_request(ses->server, timeout, optype);
++ if (rc) {
++ /*
++ * We haven't sent an SMB packet to the server yet but
++ * we already obtained credits for i requests in the
++ * compound chain - need to return those credits back
++ * for future use. Note that we need to call add_credits
++ * multiple times to match the way we obtained credits
++ * in the first place and to account for in flight
++ * requests correctly.
++ */
++ for (j = 0; j < i; j++)
++ add_credits(ses->server, 1, optype);
++ return rc;
++ }
++ credits[i] = 1;
++ }
+
+ /*
+ * Make sure that we sign in the same order that we send on this socket
+@@ -833,8 +852,10 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ for (j = 0; j < i; j++)
+ cifs_delete_mid(midQ[j]);
+ mutex_unlock(&ses->server->srv_mutex);
++
+ /* Update # of requests on wire to server */
+- add_credits(ses->server, 1, optype);
++ for (j = 0; j < num_rqst; j++)
++ add_credits(ses->server, credits[j], optype);
+ return PTR_ERR(midQ[i]);
+ }
+
+@@ -881,17 +902,16 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
+ midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
+ midQ[i]->callback = DeleteMidQEntry;
+- spin_unlock(&GlobalMid_Lock);
+- add_credits(ses->server, 1, optype);
+- return rc;
++ cancelled_mid[i] = true;
+ }
+ spin_unlock(&GlobalMid_Lock);
+ }
+ }
+
+ for (i = 0; i < num_rqst; i++)
+- if (midQ[i]->resp_buf)
+- credits += ses->server->ops->get_credits(midQ[i]);
++ if (!cancelled_mid[i] && midQ[i]->resp_buf
++ && (midQ[i]->mid_state == MID_RESPONSE_RECEIVED))
++ credits[i] = ses->server->ops->get_credits(midQ[i]);
+
+ for (i = 0; i < num_rqst; i++) {
+ if (rc < 0)
+@@ -899,8 +919,9 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+
+ rc = cifs_sync_mid_result(midQ[i], ses->server);
+ if (rc != 0) {
+- add_credits(ses->server, credits, optype);
+- return rc;
++ /* mark this mid as cancelled to not free it below */
++ cancelled_mid[i] = true;
++ goto out;
+ }
+
+ if (!midQ[i]->resp_buf ||
+@@ -947,9 +968,11 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+ * This is prevented above by using a noop callback that will not
+ * wake this thread except for the very last PDU.
+ */
+- for (i = 0; i < num_rqst; i++)
+- cifs_delete_mid(midQ[i]);
+- add_credits(ses->server, credits, optype);
++ for (i = 0; i < num_rqst; i++) {
++ if (!cancelled_mid[i])
++ cifs_delete_mid(midQ[i]);
++ add_credits(ses->server, credits[i], optype);
++ }
+
+ return rc;
+ }
+--
+2.20.1
+
diff --git a/series.conf b/series.conf
index eec0acedc5..66f07ea2a6 100644
--- a/series.conf
+++ b/series.conf
@@ -252,6 +252,7 @@
patches.kernel.org/4.20.3-012-CIFS-Fix-adjustment-of-credits-for-MTU-request.patch
patches.kernel.org/4.20.3-013-CIFS-Do-not-set-credits-to-1-if-the-server-did.patch
patches.kernel.org/4.20.3-014-CIFS-Do-not-hide-EINTR-after-sending-network-p.patch
+ patches.kernel.org/4.20.3-015-CIFS-Fix-credit-computation-for-compounded-req.patch
########################################################
# Build fixes that apply to the vanilla kernel too.