[CIFS] CIFS readdir perf optimizations part 1
[powerpc.git] / fs / cifs / misc.c
index 94baf6c..988b8ce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/misc.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -72,10 +72,9 @@ sesInfoAlloc(void)
        struct cifsSesInfo *ret_buf;
 
        ret_buf =
-           (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
+           (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
                                           GFP_KERNEL);
        if (ret_buf) {
-               memset(ret_buf, 0, sizeof (struct cifsSesInfo));
                write_lock(&GlobalSMBSeslock);
                atomic_inc(&sesInfoAllocCount);
                ret_buf->status = CifsNew;
@@ -110,10 +109,9 @@ tconInfoAlloc(void)
 {
        struct cifsTconInfo *ret_buf;
        ret_buf =
-           (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
+           (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
                                            GFP_KERNEL);
        if (ret_buf) {
-               memset(ret_buf, 0, sizeof (struct cifsTconInfo));
                write_lock(&GlobalSMBSeslock);
                atomic_inc(&tconInfoAllocCount);
                list_add(&ret_buf->cifsConnectionList,
@@ -161,6 +159,9 @@ cifs_buf_get(void)
        if (ret_buf) {
                memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
                atomic_inc(&bufAllocCount);
+#ifdef CONFIG_CIFS_STATS2
+               atomic_inc(&totBufAllocCount);
+#endif /* CONFIG_CIFS_STATS2 */
        }
 
        return ret_buf;
@@ -195,6 +196,10 @@ cifs_small_buf_get(void)
        /* No need to clear memory here, cleared in header assemble */
        /*      memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
                atomic_inc(&smBufAllocCount);
+#ifdef CONFIG_CIFS_STATS2
+               atomic_inc(&totSmBufAllocCount);
+#endif /* CONFIG_CIFS_STATS2 */
+
        }
        return ret_buf;
 }
@@ -292,7 +297,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
        struct cifsSesInfo * ses;
        char *temp = (char *) buffer;
 
-       memset(temp,0,MAX_CIFS_HDR_SIZE);
+       memset(temp,0,256); /* bigger than MAX_CIFS_HDR_SIZE */
 
        buffer->smb_buf_length =
            (2 * word_count) + sizeof (struct smb_hdr) -
@@ -348,12 +353,12 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
                /*  BB Add support for establishing new tCon and SMB Session  */
                /*      with userid/password pairs found on the smb session   */ 
                /*      for other target tcp/ip addresses               BB    */
-                               if(current->uid != treeCon->ses->linux_uid) {
-                                       cFYI(1,("Multiuser mode and UID did not match tcon uid "));
+                               if(current->fsuid != treeCon->ses->linux_uid) {
+                                       cFYI(1,("Multiuser mode and UID did not match tcon uid"));
                                        read_lock(&GlobalSMBSeslock);
                                        list_for_each(temp_item, &GlobalSMBSessionList) {
                                                ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
-                                               if(ses->linux_uid == current->uid) {
+                                               if(ses->linux_uid == current->fsuid) {
                                                        if(ses->server == treeCon->ses->server) {
                                                                cFYI(1,("found matching uid substitute right smb_uid"));  
                                                                buffer->Uid = ses->Suid;
@@ -416,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 {
        __u32 len = smb->smb_buf_length;
        __u32 clc_len;  /* calculated length */
-       cFYI(0,
-            ("Entering checkSMB with Length: %x, smb_buf_length: %x",
-             length, len));
+       cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
        if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
            (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
                if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
@@ -430,22 +433,29 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
                        } else {
                                cERROR(1, ("Length less than smb header size"));
                        }
-
                }
                if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
-                       cERROR(1,
-                              ("smb_buf_length greater than MaxBufSize"));
-               cERROR(1,
-                      ("bad smb detected. Illegal length. mid=%d",
-                       smb->Mid));
+                       cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
+                                  smb->Mid));
                return 1;
        }
 
        if (checkSMBhdr(smb, mid))
                return 1;
        clc_len = smbCalcSize_LE(smb);
-       if ((4 + len != clc_len)
-           || (4 + len != (unsigned int)length)) {
+
+       if(4 + len != (unsigned int)length) {
+               cERROR(1, ("Length read does not match RFC1001 length %d",len));
+               return 1;
+       }
+
+       if (4 + len != clc_len) {
+               /* check if bcc wrapped around for large read responses */
+               if((len > 64 * 1024) && (len > clc_len)) {
+                       /* check if lengths match mod 64K */
+                       if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
+                               return 0; /* bcc wrapped */                     
+               }
                cERROR(1, ("Calculated size 0x%x vs actual length 0x%x",
                                clc_len, 4 + len));
                cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid));