CIFS: Expand CurrentMid field

While in CIFS/SMB we have 16 bit mid, in SMB2 it is 64 bit.
Convert the existing field to 64 bit and mask off higher bits
for CIFS/SMB.

Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
This commit is contained in:
Pavel Shilovsky 2012-03-23 14:28:03 -04:00 committed by Jeff Layton
parent 5ffef7bf1d
commit 243d04b6e6
3 changed files with 48 additions and 40 deletions

View File

@ -282,7 +282,7 @@ struct TCP_Server_Info {
vcnumbers */ vcnumbers */
int capabilities; /* allow selective disabling of caps by smb sess */ int capabilities; /* allow selective disabling of caps by smb sess */
int timeAdj; /* Adjust for difference in server time zone in sec */ int timeAdj; /* Adjust for difference in server time zone in sec */
__u16 CurrentMid; /* multiplex id - rotating counter */ __u64 CurrentMid; /* multiplex id - rotating counter */
char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */
/* 16th byte of RFC1001 workstation name is always null */ /* 16th byte of RFC1001 workstation name is always null */
char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];

View File

@ -115,7 +115,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
void **request_buf); void **request_buf);
extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses,
const struct nls_table *nls_cp); const struct nls_table *nls_cp);
extern __u16 GetNextMid(struct TCP_Server_Info *server); extern __u64 GetNextMid(struct TCP_Server_Info *server);
extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
extern u64 cifs_UnixTimeToNT(struct timespec); extern u64 cifs_UnixTimeToNT(struct timespec);
extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,

View File

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