aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/misc.c84
3 files changed, 48 insertions, 40 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a40339826178..b213458b852a 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -282,7 +282,7 @@ struct TCP_Server_Info {
282 vcnumbers */ 282 vcnumbers */
283 int capabilities; /* allow selective disabling of caps by smb sess */ 283 int capabilities; /* allow selective disabling of caps by smb sess */
284 int timeAdj; /* Adjust for difference in server time zone in sec */ 284 int timeAdj; /* Adjust for difference in server time zone in sec */
285 __u16 CurrentMid; /* multiplex id - rotating counter */ 285 __u64 CurrentMid; /* multiplex id - rotating counter */
286 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ 286 char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
287 /* 16th byte of RFC1001 workstation name is always null */ 287 /* 16th byte of RFC1001 workstation name is always null */
288 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; 288 char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 05f0a2e7e14a..95ee5a64e0b0 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -115,7 +115,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
115 void **request_buf); 115 void **request_buf);
116extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, 116extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses,
117 const struct nls_table *nls_cp); 117 const struct nls_table *nls_cp);
118extern __u16 GetNextMid(struct TCP_Server_Info *server); 118extern __u64 GetNextMid(struct TCP_Server_Info *server);
119extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); 119extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
120extern u64 cifs_UnixTimeToNT(struct timespec); 120extern u64 cifs_UnixTimeToNT(struct timespec);
121extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, 121extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index dc61dff2c42a..d2ccce89062f 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -213,54 +213,61 @@ cifs_small_buf_release(void *buf_to_free)
213} 213}
214 214
215/* 215/*
216 Find a free multiplex id (SMB mid). Otherwise there could be 216 * Find a free multiplex id (SMB mid). Otherwise there could be
217 mid collisions which might cause problems, demultiplexing the 217 * mid collisions which might cause problems, demultiplexing the
218 wrong response to this request. Multiplex ids could collide if 218 * wrong response to this request. Multiplex ids could collide if
219 one of a series requests takes much longer than the others, or 219 * one of a series requests takes much longer than the others, or
220 if a very large number of long lived requests (byte range 220 * if a very large number of long lived requests (byte range
221 locks or FindNotify requests) are pending. No more than 221 * locks or FindNotify requests) are pending. No more than
222 64K-1 requests can be outstanding at one time. If no 222 * 64K-1 requests can be outstanding at one time. If no
223 mids are available, return zero. A future optimization 223 * mids are available, return zero. A future optimization
224 could make the combination of mids and uid the key we use 224 * could make the combination of mids and uid the key we use
225 to demultiplex on (rather than mid alone). 225 * to demultiplex on (rather than mid alone).
226 In addition to the above check, the cifs demultiplex 226 * In addition to the above check, the cifs demultiplex
227 code already used the command code as a secondary 227 * code already used the command code as a secondary
228 check of the frame and if signing is negotiated the 228 * check of the frame and if signing is negotiated the
229 response would be discarded if the mid were the same 229 * response would be discarded if the mid were the same
230 but the signature was wrong. Since the mid is not put in the 230 * but the signature was wrong. Since the mid is not put in the
231 pending queue until later (when it is about to be dispatched) 231 * pending queue until later (when it is about to be dispatched)
232 we do have to limit the number of outstanding requests 232 * we do have to limit the number of outstanding requests
233 to somewhat less than 64K-1 although it is hard to imagine 233 * to somewhat less than 64K-1 although it is hard to imagine
234 so many threads being in the vfs at one time. 234 * so many threads being in the vfs at one time.
235*/ 235 */
236__u16 GetNextMid(struct TCP_Server_Info *server) 236__u64 GetNextMid(struct TCP_Server_Info *server)
237{ 237{
238 __u16 mid = 0; 238 __u64 mid = 0;
239 __u16 last_mid; 239 __u16 last_mid, cur_mid;
240 bool collision; 240 bool collision;
241 241
242 spin_lock(&GlobalMid_Lock); 242 spin_lock(&GlobalMid_Lock);
243 last_mid = server->CurrentMid; /* we do not want to loop forever */ 243
244 server->CurrentMid++; 244 /* mid is 16 bit only for CIFS/SMB */
245 /* This nested loop looks more expensive than it is. 245 cur_mid = (__u16)((server->CurrentMid) & 0xffff);
246 In practice the list of pending requests is short, 246 /* we do not want to loop forever */
247 fewer than 50, and the mids are likely to be unique 247 last_mid = cur_mid;
248 on the first pass through the loop unless some request 248 cur_mid++;
249 takes longer than the 64 thousand requests before it 249
250 (and it would also have to have been a request that 250 /*
251 did not time out) */ 251 * This nested loop looks more expensive than it is.
252 while (server->CurrentMid != last_mid) { 252 * In practice the list of pending requests is short,
253 * fewer than 50, and the mids are likely to be unique
254 * on the first pass through the loop unless some request
255 * takes longer than the 64 thousand requests before it
256 * (and it would also have to have been a request that
257 * did not time out).
258 */
259 while (cur_mid != last_mid) {
253 struct mid_q_entry *mid_entry; 260 struct mid_q_entry *mid_entry;
254 unsigned int num_mids; 261 unsigned int num_mids;
255 262
256 collision = false; 263 collision = false;
257 if (server->CurrentMid == 0) 264 if (cur_mid == 0)
258 server->CurrentMid++; 265 cur_mid++;
259 266
260 num_mids = 0; 267 num_mids = 0;
261 list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { 268 list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
262 ++num_mids; 269 ++num_mids;
263 if (mid_entry->mid == server->CurrentMid && 270 if (mid_entry->mid == cur_mid &&
264 mid_entry->midState == MID_REQUEST_SUBMITTED) { 271 mid_entry->midState == MID_REQUEST_SUBMITTED) {
265 /* This mid is in use, try a different one */ 272 /* This mid is in use, try a different one */
266 collision = true; 273 collision = true;
@@ -282,10 +289,11 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
282 server->tcpStatus = CifsNeedReconnect; 289 server->tcpStatus = CifsNeedReconnect;
283 290
284 if (!collision) { 291 if (!collision) {
285 mid = server->CurrentMid; 292 mid = (__u64)cur_mid;
293 server->CurrentMid = mid;
286 break; 294 break;
287 } 295 }
288 server->CurrentMid++; 296 cur_mid++;
289 } 297 }
290 spin_unlock(&GlobalMid_Lock); 298 spin_unlock(&GlobalMid_Lock);
291 return mid; 299 return mid;