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

cifs: add compound_send_recv()

parent 1f3a8f5f
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -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 */ ,
+90 −66
Original line number Original line Diff line number Diff line
@@ -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,42 +807,52 @@ 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]);
		if (IS_ERR(midQ[i])) {
			for (j = 0; j < i; j++)
				cifs_delete_mid(midQ[j]);
			mutex_unlock(&ses->server->srv_mutex);
			mutex_unlock(&ses->server->srv_mutex);
			/* Update # of requests on wire to server */
			/* Update # of requests on wire to server */
			add_credits(ses->server, 1, optype);
			add_credits(ses->server, 1, optype);
		return PTR_ERR(midQ);
			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);


	for (i = 0; i < num_rqst; i++) {
		if (rc < 0)
		if (rc < 0)
			goto out;
			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);
			send_cancel(ses->server, &rqst[i], midQ[i]);
			spin_lock(&GlobalMid_Lock);
			spin_lock(&GlobalMid_Lock);
		if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
			if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
			midQ->mid_flags |= MID_WAIT_CANCELLED;
				midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
			midQ->callback = DeleteMidQEntry;
				midQ[i]->callback = DeleteMidQEntry;
				spin_unlock(&GlobalMid_Lock);
				spin_unlock(&GlobalMid_Lock);
				add_credits(ses->server, 1, optype);
				add_credits(ses->server, 1, optype);
				return rc;
				return rc;
@@ -849,50 +860,63 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
			spin_unlock(&GlobalMid_Lock);
			spin_unlock(&GlobalMid_Lock);
		}
		}


	rc = cifs_sync_mid_result(midQ, ses->server);
		rc = cifs_sync_mid_result(midQ[i], ses->server);
		if (rc != 0) {
		if (rc != 0) {
			add_credits(ses->server, 1, optype);
			add_credits(ses->server, 1, optype);
			return rc;
			return rc;
		}
		}


	if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
		if (!midQ[i]->resp_buf ||
		    midQ[i]->mid_state != MID_RESPONSE_RECEIVED) {
			rc = -EIO;
			rc = -EIO;
			cifs_dbg(FYI, "Bad MID state?\n");
			cifs_dbg(FYI, "Bad MID state?\n");
			goto out;
			goto out;
		}
		}


	buf = (char *)midQ->resp_buf;
		buf = (char *)midQ[i]->resp_buf;
	resp_iov->iov_base = buf;
		resp_iov[i].iov_base = buf;
	resp_iov->iov_len = midQ->resp_buf_size +
		resp_iov[i].iov_len = midQ[i]->resp_buf_size +
			ses->server->vals->header_preamble_size;
			ses->server->vals->header_preamble_size;
	if (midQ->large_buf)

		*resp_buf_type = CIFS_LARGE_BUFFER;
		if (midQ[i]->large_buf)
			resp_buf_type[i] = CIFS_LARGE_BUFFER;
		else
		else
		*resp_buf_type = CIFS_SMALL_BUFFER;
			resp_buf_type[i] = CIFS_SMALL_BUFFER;


		if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
		if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
			struct kvec iov = {
			struct kvec iov = {
			.iov_base = resp_iov->iov_base,
				.iov_base = resp_iov[i].iov_base,
			.iov_len = resp_iov->iov_len
				.iov_len = resp_iov[i].iov_len
			};
			};
			smb311_update_preauth_hash(ses, &iov, 1);
			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 */,