Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / fs / cifs / smb2pdu.c
index 50811a7dc0e0c6375fa2cdbe5e6c8474da61a8c4..77b3aaa39b35c0c6dc1c96c8bdf0542fa1bf98bc 100644 (file)
@@ -2816,6 +2816,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        int resp_buftype = CIFS_NO_BUFFER;
        struct cifs_ses *ses = tcon->ses;
        int flags = 0;
+       bool allocated = false;
 
        cifs_dbg(FYI, "Query Info\n");
 
@@ -2855,14 +2856,21 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
                                        "Error %d allocating memory for acl\n",
                                        rc);
                                *dlen = 0;
+                               rc = -ENOMEM;
                                goto qinf_exit;
                        }
+                       allocated = true;
                }
        }
 
        rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
                                        le32_to_cpu(rsp->OutputBufferLength),
                                        &rsp_iov, min_len, *data);
+       if (rc && allocated) {
+               kfree(*data);
+               *data = NULL;
+               *dlen = 0;
+       }
 
 qinf_exit:
        SMB2_query_info_free(&rqst);
@@ -2916,9 +2924,10 @@ smb2_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
        struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
-       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
                credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
 
        DeleteMidQEntry(mid);
@@ -3175,7 +3184,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
        struct TCP_Server_Info *server = tcon->ses->server;
        struct smb2_sync_hdr *shdr =
                                (struct smb2_sync_hdr *)rdata->iov[0].iov_base;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2,
                                 .rq_pages = rdata->pages,
@@ -3214,6 +3223,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
                task_io_account_read(rdata->got_bytes);
                cifs_stats_bytes_read(tcon, rdata->got_bytes);
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(shdr->CreditRequest);
+               /* fall through */
        default:
                if (rdata->result != -ENODATA)
                        rdata->result = -EIO;
@@ -3229,8 +3241,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
                rdata->mr = NULL;
        }
 #endif
-       if (rdata->result)
+       if (rdata->result && rdata->result != -ENODATA) {
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
+               trace_smb3_read_err(0 /* xid */,
+                                   rdata->cfile->fid.persistent_fid,
+                                   tcon->tid, tcon->ses->Suid, rdata->offset,
+                                   rdata->bytes, rdata->result);
+       } else
+               trace_smb3_read_done(0 /* xid */,
+                                    rdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid,
+                                    rdata->offset, rdata->got_bytes);
 
        queue_work(cifsiod_wq, &rdata->work);
        DeleteMidQEntry(mid);
@@ -3305,13 +3326,11 @@ smb2_async_readv(struct cifs_readdata *rdata)
        if (rc) {
                kref_put(&rdata->refcount, cifs_readdata_release);
                cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
-               trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
-       } else
-               trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
+               trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
+                                   io_parms.tcon->tid,
+                                   io_parms.tcon->ses->Suid,
+                                   io_parms.offset, io_parms.length, rc);
+       }
 
        cifs_small_buf_release(buf);
        return rc;
@@ -3355,10 +3374,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                if (rc != -ENODATA) {
                        cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
                        cifs_dbg(VFS, "Send error in read = %d\n", rc);
+                       trace_smb3_read_err(xid, req->PersistentFileId,
+                                           io_parms->tcon->tid, ses->Suid,
+                                           io_parms->offset, io_parms->length,
+                                           rc);
                }
-               trace_smb3_read_err(rc, xid, req->PersistentFileId,
-                                   io_parms->tcon->tid, ses->Suid,
-                                   io_parms->offset, io_parms->length);
                free_rsp_buf(resp_buftype, rsp_iov.iov_base);
                return rc == -ENODATA ? 0 : rc;
        } else
@@ -3399,7 +3419,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
        switch (mid->mid_state) {
        case MID_RESPONSE_RECEIVED:
@@ -3427,6 +3447,9 @@ smb2_writev_callback(struct mid_q_entry *mid)
        case MID_RETRY_NEEDED:
                wdata->result = -EAGAIN;
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               /* fall through */
        default:
                wdata->result = -EIO;
                break;
@@ -3444,8 +3467,17 @@ smb2_writev_callback(struct mid_q_entry *mid)
                wdata->mr = NULL;
        }
 #endif
-       if (wdata->result)
+       if (wdata->result) {
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+               trace_smb3_write_err(0 /* no xid */,
+                                    wdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid, wdata->offset,
+                                    wdata->bytes, wdata->result);
+       } else
+               trace_smb3_write_done(0 /* no xid */,
+                                     wdata->cfile->fid.persistent_fid,
+                                     tcon->tid, tcon->ses->Suid,
+                                     wdata->offset, wdata->bytes);
 
        queue_work(cifsiod_wq, &wdata->work);
        DeleteMidQEntry(mid);
@@ -3587,10 +3619,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
                                     wdata->bytes, rc);
                kref_put(&wdata->refcount, release);
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
-       } else
-               trace_smb3_write_done(0 /* no xid */, req->PersistentFileId,
-                                    tcon->tid, tcon->ses->Suid, wdata->offset,
-                                    wdata->bytes);
+       }
 
 async_writev_out:
        cifs_small_buf_release(req);
@@ -3816,8 +3845,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
                    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
                        srch_inf->endOfSearch = true;
                        rc = 0;
-               }
-               cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+               } else
+                       cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
                goto qdir_exit;
        }
 
@@ -4412,8 +4441,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
        rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
        cifs_small_buf_release(req);
 
-       please_key_low = (__u64 *)req->LeaseKey;
-       please_key_high = (__u64 *)(req->LeaseKey+8);
+       please_key_low = (__u64 *)lease_key;
+       please_key_high = (__u64 *)(lease_key+8);
        if (rc) {
                cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
                trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,