]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
CIFS: Expand CurrentMid field
authorPavel Shilovsky <piastry@etersoft.ru>
Fri, 23 Mar 2012 18:28:03 +0000 (14:28 -0400)
committerJeff Layton <jlayton@redhat.com>
Fri, 23 Mar 2012 18:28:03 +0000 (14:28 -0400)
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>
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/misc.c

index a403398261788269ea374faa5172ae66afe66a83..b213458b852a016e0045ebebae08f1c99268e251 100644 (file)
@@ -282,7 +282,7 @@ struct TCP_Server_Info {
                                   vcnumbers */
        int capabilities; /* allow selective disabling of caps by smb sess */
        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 */
        /* 16th byte of RFC1001 workstation name is always null */
        char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
index 05f0a2e7e14a5a5d3b7ef50113a4ce6bf404b9a0..95ee5a64e0b0b247e33e4c11566a3b68216b9c51 100644 (file)
@@ -115,7 +115,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
                                void **request_buf);
 extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses,
                             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 u64 cifs_UnixTimeToNT(struct timespec);
 extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
index dc61dff2c42a0304d0c387a850914761832655ec..d2ccce89062fdd7cd2b022cacc9645f049871a40 100644 (file)
@@ -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;