1 |
From 9b73f1d1e93536d231200a333018c91b2b8d89b9 Mon Sep 17 00:00:00 2001 |
2 |
From: Ronnie Sahlberg <lsahlber@redhat.com> |
3 |
Date: Wed, 10 Oct 2018 15:29:06 +1000 |
4 |
Subject: [PATCH 084/145] cifs: fix a credits leak for compund commands |
5 |
|
6 |
[ Upstream commit cb5c2e63948451d38c977685fffc06e23beb4517 ] |
7 |
|
8 |
When processing the mids for compounds we would only add credits based on |
9 |
the last successful mid in the compound which would leak credits and |
10 |
eventually triggering a re-connect. |
11 |
|
12 |
Fix this by splitting the mid processing part into two loops instead of one |
13 |
where the first loop just waits for all mids and then counts how many |
14 |
credits we were granted for the whole compound. |
15 |
|
16 |
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> |
17 |
Signed-off-by: Steve French <stfrench@microsoft.com> |
18 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
19 |
--- |
20 |
fs/cifs/transport.c | 57 +++++++++++++++++++++++++++++---------------- |
21 |
1 file changed, 37 insertions(+), 20 deletions(-) |
22 |
|
23 |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c |
24 |
index b48f43963da6..333729cf46cd 100644 |
25 |
--- a/fs/cifs/transport.c |
26 |
+++ b/fs/cifs/transport.c |
27 |
@@ -786,7 +786,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, |
28 |
int i, j, rc = 0; |
29 |
int timeout, optype; |
30 |
struct mid_q_entry *midQ[MAX_COMPOUND]; |
31 |
- unsigned int credits = 1; |
32 |
+ unsigned int credits = 0; |
33 |
char *buf; |
34 |
|
35 |
timeout = flags & CIFS_TIMEOUT_MASK; |
36 |
@@ -851,17 +851,20 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, |
37 |
|
38 |
mutex_unlock(&ses->server->srv_mutex); |
39 |
|
40 |
- for (i = 0; i < num_rqst; i++) { |
41 |
- if (rc < 0) |
42 |
- goto out; |
43 |
+ if (rc < 0) |
44 |
+ goto out; |
45 |
|
46 |
- if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) |
47 |
- smb311_update_preauth_hash(ses, rqst[i].rq_iov, |
48 |
- rqst[i].rq_nvec); |
49 |
+ /* |
50 |
+ * Compounding is never used during session establish. |
51 |
+ */ |
52 |
+ if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) |
53 |
+ smb311_update_preauth_hash(ses, rqst[0].rq_iov, |
54 |
+ rqst[0].rq_nvec); |
55 |
|
56 |
- if (timeout == CIFS_ASYNC_OP) |
57 |
- goto out; |
58 |
+ if (timeout == CIFS_ASYNC_OP) |
59 |
+ goto out; |
60 |
|
61 |
+ for (i = 0; i < num_rqst; i++) { |
62 |
rc = wait_for_response(ses->server, midQ[i]); |
63 |
if (rc != 0) { |
64 |
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", |
65 |
@@ -877,10 +880,21 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, |
66 |
} |
67 |
spin_unlock(&GlobalMid_Lock); |
68 |
} |
69 |
+ } |
70 |
+ |
71 |
+ for (i = 0; i < num_rqst; i++) |
72 |
+ if (midQ[i]->resp_buf) |
73 |
+ credits += ses->server->ops->get_credits(midQ[i]); |
74 |
+ if (!credits) |
75 |
+ credits = 1; |
76 |
+ |
77 |
+ for (i = 0; i < num_rqst; i++) { |
78 |
+ if (rc < 0) |
79 |
+ goto out; |
80 |
|
81 |
rc = cifs_sync_mid_result(midQ[i], ses->server); |
82 |
if (rc != 0) { |
83 |
- add_credits(ses->server, 1, optype); |
84 |
+ add_credits(ses->server, credits, optype); |
85 |
return rc; |
86 |
} |
87 |
|
88 |
@@ -901,23 +915,26 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, |
89 |
else |
90 |
resp_buf_type[i] = CIFS_SMALL_BUFFER; |
91 |
|
92 |
- if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { |
93 |
- struct kvec iov = { |
94 |
- .iov_base = resp_iov[i].iov_base, |
95 |
- .iov_len = resp_iov[i].iov_len |
96 |
- }; |
97 |
- smb311_update_preauth_hash(ses, &iov, 1); |
98 |
- } |
99 |
- |
100 |
- credits = ses->server->ops->get_credits(midQ[i]); |
101 |
- |
102 |
rc = ses->server->ops->check_receive(midQ[i], ses->server, |
103 |
flags & CIFS_LOG_ERROR); |
104 |
|
105 |
/* mark it so buf will not be freed by cifs_delete_mid */ |
106 |
if ((flags & CIFS_NO_RESP) == 0) |
107 |
midQ[i]->resp_buf = NULL; |
108 |
+ |
109 |
} |
110 |
+ |
111 |
+ /* |
112 |
+ * Compounding is never used during session establish. |
113 |
+ */ |
114 |
+ if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { |
115 |
+ struct kvec iov = { |
116 |
+ .iov_base = resp_iov[0].iov_base, |
117 |
+ .iov_len = resp_iov[0].iov_len |
118 |
+ }; |
119 |
+ smb311_update_preauth_hash(ses, &iov, 1); |
120 |
+ } |
121 |
+ |
122 |
out: |
123 |
/* |
124 |
* This will dequeue all mids. After this it is important that the |
125 |
-- |
126 |
2.19.1 |
127 |
|