Commit e0bba0b8 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French

cifs: add compound_send_recv()

Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Reviewed-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
parent 1f3a8f5f
...@@ -94,6 +94,10 @@ extern int cifs_call_async(struct TCP_Server_Info *server, ...@@ -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, extern int cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
struct smb_rqst *rqst, int *resp_buf_type, struct smb_rqst *rqst, int *resp_buf_type,
const int flags, struct kvec *resp_iov); 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 *, extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
struct smb_hdr * /* input */ , struct smb_hdr * /* input */ ,
struct smb_hdr * /* out */ , struct smb_hdr * /* out */ ,
......
...@@ -766,20 +766,21 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) ...@@ -766,20 +766,21 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
} }
int int
cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
struct smb_rqst *rqst, int *resp_buf_type, const int flags, const int flags, const int num_rqst, struct smb_rqst *rqst,
struct kvec *resp_iov) int *resp_buf_type, struct kvec *resp_iov)
{ {
int rc = 0; int i, j, rc = 0;
int timeout, optype; int timeout, optype;
struct mid_q_entry *midQ; struct mid_q_entry *midQ[MAX_COMPOUND];
unsigned int credits = 1; unsigned int credits = 1;
char *buf; char *buf;
timeout = flags & CIFS_TIMEOUT_MASK; timeout = flags & CIFS_TIMEOUT_MASK;
optype = flags & CIFS_OP_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)) { if ((ses == NULL) || (ses->server == NULL)) {
cifs_dbg(VFS, "Null session\n"); cifs_dbg(VFS, "Null session\n");
...@@ -806,93 +807,116 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -806,93 +807,116 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
mutex_lock(&ses->server->srv_mutex); mutex_lock(&ses->server->srv_mutex);
midQ = ses->server->ops->setup_request(ses, rqst); for (i = 0; i < num_rqst; i++) {
if (IS_ERR(midQ)) { midQ[i] = ses->server->ops->setup_request(ses, &rqst[i]);
mutex_unlock(&ses->server->srv_mutex); if (IS_ERR(midQ[i])) {
/* Update # of requests on wire to server */ for (j = 0; j < i; j++)
add_credits(ses->server, 1, optype); cifs_delete_mid(midQ[j]);
return PTR_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[i]);
}
midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
} }
midQ->mid_state = MID_REQUEST_SUBMITTED;
cifs_in_send_inc(ses->server); 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_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) if (rc < 0)
ses->server->sequence_number -= 2; ses->server->sequence_number -= 2;
mutex_unlock(&ses->server->srv_mutex); mutex_unlock(&ses->server->srv_mutex);
if (rc < 0) for (i = 0; i < num_rqst; i++) {
goto out; if (rc < 0)
goto out;
if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP))
smb311_update_preauth_hash(ses, rqst->rq_iov, smb311_update_preauth_hash(ses, rqst[i].rq_iov,
rqst->rq_nvec); rqst[i].rq_nvec);
if (timeout == CIFS_ASYNC_OP) if (timeout == CIFS_ASYNC_OP)
goto out; goto out;
rc = wait_for_response(ses->server, midQ); rc = wait_for_response(ses->server, midQ[i]);
if (rc != 0) { if (rc != 0) {
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid); cifs_dbg(FYI, "Cancelling wait for mid %llu\n",
send_cancel(ses->server, rqst, midQ); midQ[i]->mid);
spin_lock(&GlobalMid_Lock); send_cancel(ses->server, &rqst[i], midQ[i]);
if (midQ->mid_state == MID_REQUEST_SUBMITTED) { spin_lock(&GlobalMid_Lock);
midQ->mid_flags |= MID_WAIT_CANCELLED; if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
midQ->callback = DeleteMidQEntry; 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); spin_unlock(&GlobalMid_Lock);
}
rc = cifs_sync_mid_result(midQ[i], ses->server);
if (rc != 0) {
add_credits(ses->server, 1, optype); add_credits(ses->server, 1, optype);
return rc; 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) { if (!midQ[i]->resp_buf ||
rc = -EIO; midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
cifs_dbg(FYI, "Bad MID state?\n"); rc = -EIO;
goto out; 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 ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { buf = (char *)midQ[i]->resp_buf;
struct kvec iov = { resp_iov[i].iov_base = buf;
.iov_base = resp_iov->iov_base, resp_iov[i].iov_len = midQ[i]->resp_buf_size +
.iov_len = resp_iov->iov_len ses->server->vals->header_preamble_size;
};
smb311_update_preauth_hash(ses, &iov, 1); 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, rc = ses->server->ops->check_receive(midQ[i], ses->server,
flags & CIFS_LOG_ERROR); flags & CIFS_LOG_ERROR);
/* mark it so buf will not be freed by cifs_delete_mid */ /* mark it so buf will not be freed by cifs_delete_mid */
if ((flags & CIFS_NO_RESP) == 0) if ((flags & CIFS_NO_RESP) == 0)
midQ->resp_buf = NULL; midQ[i]->resp_buf = NULL;
}
out: out:
cifs_delete_mid(midQ); for (i = 0; i < num_rqst; i++)
cifs_delete_mid(midQ[i]);
add_credits(ses->server, credits, optype); add_credits(ses->server, credits, optype);
return rc; 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 int
SendReceive2(const unsigned int xid, struct cifs_ses *ses, SendReceive2(const unsigned int xid, struct cifs_ses *ses,
struct kvec *iov, int n_vec, int *resp_buf_type /* ret */, struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment