|
@@ -213,54 +213,61 @@ cifs_small_buf_release(void *buf_to_free)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- Find a free multiplex id (SMB mid). Otherwise there could be
|
|
|
- mid collisions which might cause problems, demultiplexing the
|
|
|
- wrong response to this request. Multiplex ids could collide if
|
|
|
- one of a series requests takes much longer than the others, or
|
|
|
- if a very large number of long lived requests (byte range
|
|
|
- locks or FindNotify requests) are pending. No more than
|
|
|
- 64K-1 requests can be outstanding at one time. If no
|
|
|
- mids are available, return zero. A future optimization
|
|
|
- could make the combination of mids and uid the key we use
|
|
|
- to demultiplex on (rather than mid alone).
|
|
|
- In addition to the above check, the cifs demultiplex
|
|
|
- code already used the command code as a secondary
|
|
|
- check of the frame and if signing is negotiated the
|
|
|
- response would be discarded if the mid were the same
|
|
|
- but the signature was wrong. Since the mid is not put in the
|
|
|
- pending queue until later (when it is about to be dispatched)
|
|
|
- we do have to limit the number of outstanding requests
|
|
|
- to somewhat less than 64K-1 although it is hard to imagine
|
|
|
- so many threads being in the vfs at one time.
|
|
|
-*/
|
|
|
-__u16 GetNextMid(struct TCP_Server_Info *server)
|
|
|
+ * Find a free multiplex id (SMB mid). Otherwise there could be
|
|
|
+ * mid collisions which might cause problems, demultiplexing the
|
|
|
+ * wrong response to this request. Multiplex ids could collide if
|
|
|
+ * one of a series requests takes much longer than the others, or
|
|
|
+ * if a very large number of long lived requests (byte range
|
|
|
+ * locks or FindNotify requests) are pending. No more than
|
|
|
+ * 64K-1 requests can be outstanding at one time. If no
|
|
|
+ * mids are available, return zero. A future optimization
|
|
|
+ * could make the combination of mids and uid the key we use
|
|
|
+ * to demultiplex on (rather than mid alone).
|
|
|
+ * In addition to the above check, the cifs demultiplex
|
|
|
+ * code already used the command code as a secondary
|
|
|
+ * check of the frame and if signing is negotiated the
|
|
|
+ * response would be discarded if the mid were the same
|
|
|
+ * but the signature was wrong. Since the mid is not put in the
|
|
|
+ * pending queue until later (when it is about to be dispatched)
|
|
|
+ * we do have to limit the number of outstanding requests
|
|
|
+ * to somewhat less than 64K-1 although it is hard to imagine
|
|
|
+ * so many threads being in the vfs at one time.
|
|
|
+ */
|
|
|
+__u64 GetNextMid(struct TCP_Server_Info *server)
|
|
|
{
|
|
|
- __u16 mid = 0;
|
|
|
- __u16 last_mid;
|
|
|
+ __u64 mid = 0;
|
|
|
+ __u16 last_mid, cur_mid;
|
|
|
bool collision;
|
|
|
|
|
|
spin_lock(&GlobalMid_Lock);
|
|
|
- last_mid = server->CurrentMid; /* we do not want to loop forever */
|
|
|
- server->CurrentMid++;
|
|
|
- /* This nested loop looks more expensive than it is.
|
|
|
- In practice the list of pending requests is short,
|
|
|
- fewer than 50, and the mids are likely to be unique
|
|
|
- on the first pass through the loop unless some request
|
|
|
- takes longer than the 64 thousand requests before it
|
|
|
- (and it would also have to have been a request that
|
|
|
- did not time out) */
|
|
|
- while (server->CurrentMid != last_mid) {
|
|
|
+
|
|
|
+ /* mid is 16 bit only for CIFS/SMB */
|
|
|
+ cur_mid = (__u16)((server->CurrentMid) & 0xffff);
|
|
|
+ /* we do not want to loop forever */
|
|
|
+ last_mid = cur_mid;
|
|
|
+ cur_mid++;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This nested loop looks more expensive than it is.
|
|
|
+ * In practice the list of pending requests is short,
|
|
|
+ * fewer than 50, and the mids are likely to be unique
|
|
|
+ * on the first pass through the loop unless some request
|
|
|
+ * takes longer than the 64 thousand requests before it
|
|
|
+ * (and it would also have to have been a request that
|
|
|
+ * did not time out).
|
|
|
+ */
|
|
|
+ while (cur_mid != last_mid) {
|
|
|
struct mid_q_entry *mid_entry;
|
|
|
unsigned int num_mids;
|
|
|
|
|
|
collision = false;
|
|
|
- if (server->CurrentMid == 0)
|
|
|
- server->CurrentMid++;
|
|
|
+ if (cur_mid == 0)
|
|
|
+ cur_mid++;
|
|
|
|
|
|
num_mids = 0;
|
|
|
list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
|
|
|
++num_mids;
|
|
|
- if (mid_entry->mid == server->CurrentMid &&
|
|
|
+ if (mid_entry->mid == cur_mid &&
|
|
|
mid_entry->midState == MID_REQUEST_SUBMITTED) {
|
|
|
/* This mid is in use, try a different one */
|
|
|
collision = true;
|
|
@@ -282,10 +289,11 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
|
|
|
server->tcpStatus = CifsNeedReconnect;
|
|
|
|
|
|
if (!collision) {
|
|
|
- mid = server->CurrentMid;
|
|
|
+ mid = (__u64)cur_mid;
|
|
|
+ server->CurrentMid = mid;
|
|
|
break;
|
|
|
}
|
|
|
- server->CurrentMid++;
|
|
|
+ cur_mid++;
|
|
|
}
|
|
|
spin_unlock(&GlobalMid_Lock);
|
|
|
return mid;
|