cifs: add compound_send_recv()
authorRonnie Sahlberg <lsahlber@redhat.com>
Tue, 31 Jul 2018 23:26:13 +0000 (09:26 +1000)
committerSteve French <stfrench@microsoft.com>
Tue, 7 Aug 2018 19:23:20 +0000 (14:23 -0500)
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
fs/cifs/cifsproto.h
fs/cifs/transport.c

index 7ead1a9..20adda4 100644 (file)
@@ -94,6 +94,10 @@ extern int cifs_call_async(struct TCP_Server_Info *server,
 extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
                          struct smb_rqst *rqst, int *resp_buf_type,
                          const int flags, struct kvec *resp_iov);
+extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+                             const int flags, const int num_rqst,
+                             struct smb_rqst *rqst, int *resp_buf_type,
+                             struct kvec *resp_iov);
 extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
                        struct smb_hdr * /* input */ ,
                        struct smb_hdr * /* out */ ,
index 169e767..0b9d0e8 100644 (file)
@@ -766,20 +766,21 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
 }
 
 int
-cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
-              struct smb_rqst *rqst, int *resp_buf_type, const int flags,
-              struct kvec *resp_iov)
+compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
+                  const int flags, const int num_rqst, struct smb_rqst *rqst,
+                  int *resp_buf_type, struct kvec *resp_iov)
 {
-       int rc = 0;
+       int i, j, rc = 0;
        int timeout, optype;
-       struct mid_q_entry *midQ;
+       struct mid_q_entry *midQ[MAX_COMPOUND];
        unsigned int credits = 1;
        char *buf;
 
        timeout = flags & CIFS_TIMEOUT_MASK;
        optype = flags & CIFS_OP_MASK;
 
-       *resp_buf_type = CIFS_NO_BUFFER;  /* no response buf yet */
+       for (i = 0; i < num_rqst; i++)
+               resp_buf_type[i] = CIFS_NO_BUFFER;  /* no response buf yet */
 
        if ((ses == NULL) || (ses->server == NULL)) {
                cifs_dbg(VFS, "Null session\n");
@@ -806,94 +807,117 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
        mutex_lock(&ses->server->srv_mutex);
 
-       midQ = ses->server->ops->setup_request(ses, rqst);
-       if (IS_ERR(midQ)) {
-               mutex_unlock(&ses->server->srv_mutex);
-               /* Update # of requests on wire to server */
-               add_credits(ses->server, 1, optype);
-               return PTR_ERR(midQ);
+       for (i = 0; i < num_rqst; i++) {
+               midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]);
+               if (IS_ERR(midQ[i])) {
+                       for (j = 0; j < i; j++)
+                               cifs_delete_mid(midQ[j]);
+                       mutex_unlock(&ses->server->srv_mutex);
+                       /* Update # of requests on wire to server */
+                       add_credits(ses->server, 1, optype);
+                       return PTR_ERR(midQ[i]);
+               }
+
+               midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
        }
 
-       midQ->mid_state = MID_REQUEST_SUBMITTED;
        cifs_in_send_inc(ses->server);
-       rc = smb_send_rqst(ses->server, 1, rqst, flags);
+       rc = smb_send_rqst(ses->server, num_rqst, rqst, flags);
        cifs_in_send_dec(ses->server);
-       cifs_save_when_sent(midQ);
+
+       for (i = 0; i < num_rqst; i++)
+               cifs_save_when_sent(midQ[i]);
 
        if (rc < 0)
                ses->server->sequence_number -= 2;
+
        mutex_unlock(&ses->server->srv_mutex);
 
-       if (rc < 0)
-               goto out;
+       for (i = 0; i < num_rqst; i++) {
+               if (rc < 0)
+                       goto out;
 
-       if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP))
-               smb311_update_preauth_hash(ses, rqst->rq_iov,
-                                          rqst->rq_nvec);
+               if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP))
+                       smb311_update_preauth_hash(ses, rqst[i].rq_iov,
+                                                  rqst[i].rq_nvec);
 
-       if (timeout == CIFS_ASYNC_OP)
-               goto out;
+               if (timeout == CIFS_ASYNC_OP)
+                       goto out;
 
-       rc = wait_for_response(ses->server, midQ);
-       if (rc != 0) {
-               cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
-               send_cancel(ses->server, rqst, midQ);
-               spin_lock(&GlobalMid_Lock);
-               if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
-                       midQ->mid_flags |= MID_WAIT_CANCELLED;
-                       midQ->callback = DeleteMidQEntry;
+               rc = wait_for_response(ses->server, midQ[i]);
+               if (rc != 0) {
+                       cifs_dbg(FYI, "Cancelling wait for mid %llu\n",
+                                midQ[i]->mid);
+                       send_cancel(ses->server, &rqst[i], midQ[i]);
+                       spin_lock(&GlobalMid_Lock);
+                       if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
+                               midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
+                               midQ[i]->callback = DeleteMidQEntry;
+                               spin_unlock(&GlobalMid_Lock);
+                               add_credits(ses->server, 1, optype);
+                               return rc;
+                       }
                        spin_unlock(&GlobalMid_Lock);
+               }
+
+               rc = cifs_sync_mid_result(midQ[i], ses->server);
+               if (rc != 0) {
                        add_credits(ses->server, 1, optype);
                        return rc;
                }
-               spin_unlock(&GlobalMid_Lock);
-       }
-
-       rc = cifs_sync_mid_result(midQ, ses->server);
-       if (rc != 0) {
-               add_credits(ses->server, 1, optype);
-               return rc;
-       }
 
-       if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
-               rc = -EIO;
-               cifs_dbg(FYI, "Bad MID state?\n");
-               goto out;
-       }
-
-       buf = (char *)midQ->resp_buf;
-       resp_iov->iov_base = buf;
-       resp_iov->iov_len = midQ->resp_buf_size +
-               ses->server->vals->header_preamble_size;
-       if (midQ->large_buf)
-               *resp_buf_type = CIFS_LARGE_BUFFER;
-       else
-               *resp_buf_type = CIFS_SMALL_BUFFER;
+               if (!midQ[i]->resp_buf ||
+                   midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
+                       rc = -EIO;
+                       cifs_dbg(FYI, "Bad MID state?\n");
+                       goto out;
+               }
 
-       if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
-               struct kvec iov = {
-                       .iov_base = resp_iov->iov_base,
-                       .iov_len = resp_iov->iov_len
-               };
-               smb311_update_preauth_hash(ses, &iov, 1);
-       }
+               buf = (char *)midQ[i]->resp_buf;
+               resp_iov[i].iov_base = buf;
+               resp_iov[i].iov_len = midQ[i]->resp_buf_size +
+                       ses->server->vals->header_preamble_size;
+
+               if (midQ[i]->large_buf)
+                       resp_buf_type[i] = CIFS_LARGE_BUFFER;
+               else
+                       resp_buf_type[i] = CIFS_SMALL_BUFFER;
+
+               if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
+                       struct kvec iov = {
+                               .iov_base = resp_iov[i].iov_base,
+                               .iov_len = resp_iov[i].iov_len
+                       };
+                       smb311_update_preauth_hash(ses, &iov, 1);
+               }
 
-       credits = ses->server->ops->get_credits(midQ);
+               credits = ses->server->ops->get_credits(midQ[i]);
 
-       rc = ses->server->ops->check_receive(midQ, ses->server,
-                                            flags & CIFS_LOG_ERROR);
+               rc = ses->server->ops->check_receive(midQ[i], ses->server,
+                                                    flags & CIFS_LOG_ERROR);
 
-       /* mark it so buf will not be freed by cifs_delete_mid */
-       if ((flags & CIFS_NO_RESP) == 0)
-               midQ->resp_buf = NULL;
+               /* mark it so buf will not be freed by cifs_delete_mid */
+               if ((flags & CIFS_NO_RESP) == 0)
+                       midQ[i]->resp_buf = NULL;
+       }
 out:
-       cifs_delete_mid(midQ);
+       for (i = 0; i < num_rqst; i++)
+               cifs_delete_mid(midQ[i]);
        add_credits(ses->server, credits, optype);
 
        return rc;
 }
 
 int
+cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
+              struct smb_rqst *rqst, int *resp_buf_type, const int flags,
+              struct kvec *resp_iov)
+{
+       return compound_send_recv(xid, ses, flags, 1, rqst, resp_buf_type,
+                                 resp_iov);
+}
+
+int
 SendReceive2(const unsigned int xid, struct cifs_ses *ses,
             struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
             const int flags, struct kvec *resp_iov)