mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
cifs: add compound_send_recv()
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
This commit is contained in:
parent
1f3a8f5f7a
commit
e0bba0b854
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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);
|
|
||||||
|
if (!midQ[i]->resp_buf ||
|
||||||
|
midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
|
||||||
|
rc = -EIO;
|
||||||
|
cifs_dbg(FYI, "Bad MID state?\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
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[i]);
|
||||||
|
|
||||||
|
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[i]->resp_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ((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);
|
|
||||||
}
|
|
||||||
|
|
||||||
credits = ses->server->ops->get_credits(midQ);
|
|
||||||
|
|
||||||
rc = ses->server->ops->check_receive(midQ, 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;
|
|
||||||
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 */,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user