diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/misc.c | 84 |
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); |
116 | extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, | 116 | extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, |
117 | const struct nls_table *nls_cp); | 117 | const struct nls_table *nls_cp); |
118 | extern __u16 GetNextMid(struct TCP_Server_Info *server); | 118 | extern __u64 GetNextMid(struct TCP_Server_Info *server); |
119 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); | 119 | extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); |
120 | extern u64 cifs_UnixTimeToNT(struct timespec); | 120 | extern u64 cifs_UnixTimeToNT(struct timespec); |
121 | extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, | 121 | extern 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; |