aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index af13e526b150..0046c219833d 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/transport.c 2 * fs/cifs/transport.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -41,7 +41,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41 struct mid_q_entry *temp; 41 struct mid_q_entry *temp;
42 42
43 if (ses == NULL) { 43 if (ses == NULL) {
44 cERROR(1, ("Null session passed in to AllocMidQEntry ")); 44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
45 return NULL; 45 return NULL;
46 } 46 }
47 if (ses->server == NULL) { 47 if (ses->server == NULL) {
@@ -79,7 +79,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
79 list_del(&midEntry->qhead); 79 list_del(&midEntry->qhead);
80 atomic_dec(&midCount); 80 atomic_dec(&midCount);
81 spin_unlock(&GlobalMid_Lock); 81 spin_unlock(&GlobalMid_Lock);
82 cifs_buf_release(midEntry->resp_buf); 82 if(midEntry->largeBuf)
83 cifs_buf_release(midEntry->resp_buf);
84 else
85 cifs_small_buf_release(midEntry->resp_buf);
83 mempool_free(midEntry, cifs_mid_poolp); 86 mempool_free(midEntry, cifs_mid_poolp);
84} 87}
85 88
@@ -182,14 +185,14 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
182 185
183int 186int
184smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, 187smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
185 unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin) 188 unsigned int smb_buf_length, struct kvec * write_vector
189 /* page list */, struct sockaddr *sin)
186{ 190{
187 int rc = 0; 191 int rc = 0;
188 int i = 0; 192 int i = 0;
189 struct msghdr smb_msg; 193 struct msghdr smb_msg;
190 number_of_pages += 1; /* account for SMB header */ 194 number_of_pages += 1; /* account for SMB header */
191 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); 195 struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec));
192 if(i=0;i<num_pages-1;i++
193 unsigned len = smb_buf_length + 4; 196 unsigned len = smb_buf_length + 4;
194 197
195 if(ssocket == NULL) 198 if(ssocket == NULL)
@@ -213,7 +216,8 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
213 dump_smb(smb_buffer, len); 216 dump_smb(smb_buffer, len);
214 217
215 while (len > 0) { 218 while (len > 0) {
216 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?); 219 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages,
220 len);
217 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 221 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
218 i++; 222 i++;
219 if(i > 60) { 223 if(i > 60) {
@@ -266,6 +270,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
266 270
267 271
268 272
273 if(ses->server->tcpStatus == CIFS_EXITING)
274 return -ENOENT;
275
269 /* Ensure that we do not send more than 50 overlapping requests 276 /* Ensure that we do not send more than 50 overlapping requests
270 to the same server. We may make this configurable later or 277 to the same server. We may make this configurable later or
271 use ses->maxReq */ 278 use ses->maxReq */
@@ -346,11 +353,12 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
346 } 353 }
347 354
348 /* BB can we sign efficiently in this path? */ 355 /* BB can we sign efficiently in this path? */
349 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 356 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
350 357
351 midQ->midState = MID_REQUEST_SUBMITTED; 358 midQ->midState = MID_REQUEST_SUBMITTED;
352/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, 359/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
353 (struct sockaddr *) &(ses->server->addr.sockAddr));*/ 360 piovec,
361 (struct sockaddr *) &(ses->server->addr.sockAddr));*/
354 if(rc < 0) { 362 if(rc < 0) {
355 DeleteMidQEntry(midQ); 363 DeleteMidQEntry(midQ);
356 up(&ses->server->tcpSem); 364 up(&ses->server->tcpSem);
@@ -396,6 +404,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
396 return -EIO; 404 return -EIO;
397 } 405 }
398 406
407 if(ses->server->tcpStatus == CifsExiting)
408 return -ENOENT;
409
399 /* Ensure that we do not send more than 50 overlapping requests 410 /* Ensure that we do not send more than 50 overlapping requests
400 to the same server. We may make this configurable later or 411 to the same server. We may make this configurable later or
401 use ses->maxReq */ 412 use ses->maxReq */
@@ -405,7 +416,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
405 } else { 416 } else {
406 spin_lock(&GlobalMid_Lock); 417 spin_lock(&GlobalMid_Lock);
407 while(1) { 418 while(1) {
408 if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ 419 if(atomic_read(&ses->server->inFlight) >=
420 cifs_max_pending){
409 spin_unlock(&GlobalMid_Lock); 421 spin_unlock(&GlobalMid_Lock);
410 wait_event(ses->server->request_q, 422 wait_event(ses->server->request_q,
411 atomic_read(&ses->server->inFlight) 423 atomic_read(&ses->server->inFlight)
@@ -475,7 +487,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
475 return -EIO; 487 return -EIO;
476 } 488 }
477 489
478 rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); 490 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
479 491
480 midQ->midState = MID_REQUEST_SUBMITTED; 492 midQ->midState = MID_REQUEST_SUBMITTED;
481 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, 493 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
@@ -493,7 +505,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
493 up(&ses->server->tcpSem); 505 up(&ses->server->tcpSem);
494 if (long_op == -1) 506 if (long_op == -1)
495 goto cifs_no_response_exit; 507 goto cifs_no_response_exit;
496 else if (long_op == 2) /* writes past end of file can take looooong time */ 508 else if (long_op == 2) /* writes past end of file can take loong time */
497 timeout = 300 * HZ; 509 timeout = 300 * HZ;
498 else if (long_op == 1) 510 else if (long_op == 1)
499 timeout = 45 * HZ; /* should be greater than 511 timeout = 45 * HZ; /* should be greater than
@@ -559,8 +571,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
559 } 571 }
560 572
561 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 573 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
562 cERROR(1, 574 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
563 ("Frame too large received. Length: %d Xid: %d",
564 receive_len, xid)); 575 receive_len, xid));
565 rc = -EIO; 576 rc = -EIO;
566 } else { /* rcvd frame is ok */ 577 } else { /* rcvd frame is ok */
@@ -575,15 +586,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
575 dump_smb(out_buf, 92); 586 dump_smb(out_buf, 92);
576 /* convert the length into a more usable form */ 587 /* convert the length into a more usable form */
577 if((receive_len > 24) && 588 if((receive_len > 24) &&
578 (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { 589 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
579 rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */ 590 SECMODE_SIGN_ENABLED))) {
580 if(rc) 591 rc = cifs_verify_signature(out_buf,
581 cFYI(1,("Unexpected signature received from server")); 592 ses->server->mac_signing_key,
593 midQ->sequence_number+1);
594 if(rc) {
595 cERROR(1,("Unexpected SMB signature"));
596 /* BB FIXME add code to kill session */
597 }
582 } 598 }
583 599
584 *pbytes_returned = out_buf->smb_buf_length; 600 *pbytes_returned = out_buf->smb_buf_length;
585 601
586 /* BB special case reconnect tid and reconnect uid here? */ 602 /* BB special case reconnect tid and uid here? */
587 rc = map_smb_to_linux_error(out_buf); 603 rc = map_smb_to_linux_error(out_buf);
588 604
589 /* convert ByteCount if necessary */ 605 /* convert ByteCount if necessary */