[Bluetooth] Fix NULL pointer dereferences of the HCI socket
[pandora-kernel.git] / fs / cifs / transport.c
index d9b1169..b12cb8a 100644 (file)
@@ -59,7 +59,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
                temp->pid = current->pid;
                temp->command = smb_buffer->Command;
                cFYI(1, ("For smb_command %d", temp->command));
-               do_gettimeofday(&temp->when_sent);
+       /*      do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
+               /* when mid allocated can be before when sent */
+               temp->when_alloc = jiffies;
                temp->ses = ses;
                temp->tsk = current;
        }
@@ -75,6 +77,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
 static void
 DeleteMidQEntry(struct mid_q_entry *midEntry)
 {
+#ifdef CONFIG_CIFS_STATS2
+       unsigned long now;
+#endif
        spin_lock(&GlobalMid_Lock);
        midEntry->midState = MID_FREE;
        list_del(&midEntry->qhead);
@@ -84,6 +89,22 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
                cifs_buf_release(midEntry->resp_buf);
        else
                cifs_small_buf_release(midEntry->resp_buf);
+#ifdef CONFIG_CIFS_STATS2
+       now = jiffies;
+       /* commands taking longer than one second are indications that
+          something is wrong, unless it is quite a slow link or server */
+       if((now - midEntry->when_alloc) > HZ) {
+               if((cifsFYI & CIFS_TIMER) && 
+                  (midEntry->command != SMB_COM_LOCKING_ANDX)) {
+                       printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
+                              midEntry->command, midEntry->mid);
+                       printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
+                              now - midEntry->when_alloc,
+                              now - midEntry->when_sent,
+                              now - midEntry->when_received);
+               }
+       }
+#endif
        mempool_free(midEntry, cifs_mid_poolp);
 }
 
@@ -169,6 +190,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
                }
                if (rc < 0) 
                        break;
+               else
+                       i = 0; /* reset i after each successful send */
                iov.iov_base += rc;
                iov.iov_len -= rc;
                len -= rc;
@@ -183,7 +206,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
        return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static int
 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
          struct sockaddr *sin)
@@ -263,6 +285,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
                                }
                        }
                }
+               i = 0; /* in case we get ENOSPC on the next send */
        }
 
        if (rc < 0) {
@@ -275,7 +298,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
 
 int
 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 
-            struct kvec *iov, int n_vec, int *pbytes_returned,
+            struct kvec *iov, int n_vec, int * pRespBufType /* ret */, 
             const int long_op)
 {
        int rc = 0;
@@ -283,6 +306,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
        unsigned long timeout;
        struct mid_q_entry *midQ;
        struct smb_hdr *in_buf = iov[0].iov_base;
+       
+       *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
 
        if (ses == NULL) {
                cERROR(1,("Null smb session"));
@@ -368,8 +393,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                return -ENOMEM;
        }
 
-/* BB FIXME */
-/*     rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
+       rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
 
        midQ->midState = MID_REQUEST_SUBMITTED;
 #ifdef CONFIG_CIFS_STATS2
@@ -379,6 +403,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                      (struct sockaddr *) &(ses->server->addr.sockAddr));
 #ifdef CONFIG_CIFS_STATS2
        atomic_dec(&ses->server->inSend);
+       midQ->when_sent = jiffies;
 #endif
        if(rc < 0) {
                DeleteMidQEntry(midQ);
@@ -464,21 +489,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                        receive_len, xid));
                rc = -EIO;
        } else {                /* rcvd frame is ok */
-
                if (midQ->resp_buf && 
                        (midQ->midState == MID_RESPONSE_RECEIVED)) {
-                       in_buf->smb_buf_length = receive_len;
-                       /* BB verify that length would not overrun small buf */
-                       memcpy((char *)in_buf + 4,
-                              (char *)midQ->resp_buf + 4,
-                              receive_len);
 
-                       dump_smb(in_buf, 80);
+                       iov[0].iov_base = (char *)midQ->resp_buf;
+                       if(midQ->largeBuf)
+                               *pRespBufType = CIFS_LARGE_BUFFER;
+                       else
+                               *pRespBufType = CIFS_SMALL_BUFFER;
+                       iov[0].iov_len = receive_len + 4;
+
+                       dump_smb(midQ->resp_buf, 80);
                        /* convert the length into a more usable form */
                        if((receive_len > 24) &&
                           (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
                                        SECMODE_SIGN_ENABLED))) {
-                               rc = cifs_verify_signature(in_buf,
+                               rc = cifs_verify_signature(midQ->resp_buf,
                                                ses->server->mac_signing_key,
                                                midQ->sequence_number+1);
                                if(rc) {
@@ -487,17 +513,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
                                }
                        }
 
-                       *pbytes_returned = in_buf->smb_buf_length;
-
                        /* BB special case reconnect tid and uid here? */
-                       rc = map_smb_to_linux_error(in_buf);
+                       /* BB special case Errbadpassword and pwdexpired here */
+                       rc = map_smb_to_linux_error(midQ->resp_buf);
 
                        /* convert ByteCount if necessary */
                        if (receive_len >=
                            sizeof (struct smb_hdr) -
                            4 /* do not count RFC1001 header */  +
-                           (2 * in_buf->WordCount) + 2 /* bcc */ )
-                               BCC(in_buf) = le16_to_cpu(BCC(in_buf));
+                           (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
+                               BCC(midQ->resp_buf) = 
+                                       le16_to_cpu(BCC_LE(midQ->resp_buf));
+                       midQ->resp_buf = NULL;  /* mark it so will not be freed
+                                               by DeleteMidQEntry */
                } else {
                        rc = -EIO;
                        cFYI(1,("Bad MID state?"));
@@ -523,7 +551,6 @@ out_unlock2:
 
        return rc;
 }
-#endif /* CIFS_EXPERIMENTAL */
 
 int
 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
@@ -643,6 +670,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
                      (struct sockaddr *) &(ses->server->addr.sockAddr));
 #ifdef CONFIG_CIFS_STATS2
        atomic_dec(&ses->server->inSend);
+       midQ->when_sent = jiffies;
 #endif
        if(rc < 0) {
                DeleteMidQEntry(midQ);
@@ -760,10 +788,10 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
                            sizeof (struct smb_hdr) -
                            4 /* do not count RFC1001 header */  +
                            (2 * out_buf->WordCount) + 2 /* bcc */ )
-                               BCC(out_buf) = le16_to_cpu(BCC(out_buf));
+                               BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
                } else {
                        rc = -EIO;
-                       cERROR(1,("Bad MID state? "));
+                       cERROR(1,("Bad MID state?"));
                }
        }
 cifs_no_response_exit: