diff options
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r-- | fs/cifs/transport.c | 54 |
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 | ||
183 | int | 186 | int |
184 | smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, | 187 | smb_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 */ |