+ *ppmidQ = AllocMidQEntry(in_buf, ses);
+ if (*ppmidQ == NULL) {
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int wait_for_response(struct cifsSesInfo *ses,
+ struct mid_q_entry *midQ,
+ unsigned long timeout,
+ unsigned long time_to_wait)
+{
+ unsigned long curr_timeout;
+
+ for (;;) {
+ curr_timeout = timeout + jiffies;
+ wait_event(ses->server->response_q,
+ (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
+ time_after(jiffies, curr_timeout) ||
+ ((ses->server->tcpStatus != CifsGood) &&
+ (ses->server->tcpStatus != CifsNew)));
+
+ if (time_after(jiffies, curr_timeout) &&
+ (midQ->midState == MID_REQUEST_SUBMITTED) &&
+ ((ses->server->tcpStatus == CifsGood) ||
+ (ses->server->tcpStatus == CifsNew))) {
+
+ unsigned long lrt;
+
+ /* We timed out. Is the server still
+ sending replies ? */
+ spin_lock(&GlobalMid_Lock);
+ lrt = ses->server->lstrp;
+ spin_unlock(&GlobalMid_Lock);
+
+ /* Calculate time_to_wait past last receive time.
+ Although we prefer not to time out if the
+ server is still responding - we will time
+ out if the server takes more than 15 (or 45
+ or 180) seconds to respond to this request
+ and has not responded to any request from
+ other threads on the client within 10 seconds */
+ lrt += time_to_wait;
+ if (time_after(jiffies, lrt)) {
+ /* No replies for time_to_wait. */
+ cERROR(1,("server not responding"));
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+ }
+}
+
+int
+SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
+ struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
+ const int long_op)
+{
+ int rc = 0;
+ unsigned int receive_len;
+ unsigned long timeout;
+ struct mid_q_entry *midQ;
+ struct smb_hdr *in_buf = iov[0].iov_base;
+
+ *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
+
+ if ((ses == NULL) || (ses->server == NULL)) {
+ cifs_small_buf_release(in_buf);
+ cERROR(1,("Null session"));
+ return -EIO;
+ }
+
+ if(ses->server->tcpStatus == CifsExiting) {
+ cifs_small_buf_release(in_buf);
+ return -ENOENT;
+ }
+
+ /* Ensure that we do not send more than 50 overlapping requests
+ to the same server. We may make this configurable later or
+ use ses->maxReq */
+
+ rc = wait_for_free_request(ses, long_op);
+ if (rc) {
+ cifs_small_buf_release(in_buf);
+ return rc;
+ }
+
+ /* make sure that we sign in the same order that we send on this socket
+ and avoid races inside tcp sendmsg code that could cause corruption
+ of smb data */
+
+ down(&ses->server->tcpSem);
+
+ rc = allocate_mid(ses, in_buf, &midQ);
+ if (rc) {