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:
parent
5ffef7bf1d
commit
243d04b6e6
|
@ -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];
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue