diff options
-rw-r--r-- | fs/cifs/transport.c | 110 |
1 files changed, 17 insertions, 93 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 15059c7ef2ae..c41c9c4f0a79 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -318,48 +318,17 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, | |||
318 | return 0; | 318 | return 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | static int wait_for_response(struct cifsSesInfo *ses, | 321 | static int |
322 | struct mid_q_entry *midQ, | 322 | wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) |
323 | unsigned long timeout, | ||
324 | unsigned long time_to_wait) | ||
325 | { | 323 | { |
326 | unsigned long curr_timeout; | 324 | int error; |
327 | |||
328 | for (;;) { | ||
329 | curr_timeout = timeout + jiffies; | ||
330 | wait_event_timeout(ses->server->response_q, | ||
331 | midQ->midState != MID_REQUEST_SUBMITTED, timeout); | ||
332 | |||
333 | if (time_after(jiffies, curr_timeout) && | ||
334 | (midQ->midState == MID_REQUEST_SUBMITTED) && | ||
335 | ((ses->server->tcpStatus == CifsGood) || | ||
336 | (ses->server->tcpStatus == CifsNew))) { | ||
337 | |||
338 | unsigned long lrt; | ||
339 | 325 | ||
340 | /* We timed out. Is the server still | 326 | error = wait_event_killable(server->response_q, |
341 | sending replies ? */ | 327 | midQ->midState != MID_REQUEST_SUBMITTED); |
342 | spin_lock(&GlobalMid_Lock); | 328 | if (error < 0) |
343 | lrt = ses->server->lstrp; | 329 | return -ERESTARTSYS; |
344 | spin_unlock(&GlobalMid_Lock); | ||
345 | 330 | ||
346 | /* Calculate time_to_wait past last receive time. | 331 | return 0; |
347 | Although we prefer not to time out if the | ||
348 | server is still responding - we will time | ||
349 | out if the server takes more than 15 (or 45 | ||
350 | or 180) seconds to respond to this request | ||
351 | and has not responded to any request from | ||
352 | other threads on the client within 10 seconds */ | ||
353 | lrt += time_to_wait; | ||
354 | if (time_after(jiffies, lrt)) { | ||
355 | /* No replies for time_to_wait. */ | ||
356 | cERROR(1, "server not responding"); | ||
357 | return -1; | ||
358 | } | ||
359 | } else { | ||
360 | return 0; | ||
361 | } | ||
362 | } | ||
363 | } | 332 | } |
364 | 333 | ||
365 | 334 | ||
@@ -433,7 +402,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
433 | int rc = 0; | 402 | int rc = 0; |
434 | int long_op; | 403 | int long_op; |
435 | unsigned int receive_len; | 404 | unsigned int receive_len; |
436 | unsigned long timeout; | ||
437 | struct mid_q_entry *midQ; | 405 | struct mid_q_entry *midQ; |
438 | struct smb_hdr *in_buf = iov[0].iov_base; | 406 | struct smb_hdr *in_buf = iov[0].iov_base; |
439 | 407 | ||
@@ -500,33 +468,12 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
500 | if (rc < 0) | 468 | if (rc < 0) |
501 | goto out; | 469 | goto out; |
502 | 470 | ||
503 | if (long_op == CIFS_STD_OP) | 471 | if (long_op == CIFS_ASYNC_OP) |
504 | timeout = 15 * HZ; | ||
505 | else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */ | ||
506 | timeout = 180 * HZ; | ||
507 | else if (long_op == CIFS_LONG_OP) | ||
508 | timeout = 45 * HZ; /* should be greater than | ||
509 | servers oplock break timeout (about 43 seconds) */ | ||
510 | else if (long_op == CIFS_ASYNC_OP) | ||
511 | goto out; | ||
512 | else if (long_op == CIFS_BLOCKING_OP) | ||
513 | timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */ | ||
514 | else { | ||
515 | cERROR(1, "unknown timeout flag %d", long_op); | ||
516 | rc = -EIO; | ||
517 | goto out; | 472 | goto out; |
518 | } | ||
519 | |||
520 | /* wait for 15 seconds or until woken up due to response arriving or | ||
521 | due to last connection to this server being unmounted */ | ||
522 | if (signal_pending(current)) { | ||
523 | /* if signal pending do not hold up user for full smb timeout | ||
524 | but we still give response a chance to complete */ | ||
525 | timeout = 2 * HZ; | ||
526 | } | ||
527 | 473 | ||
528 | /* No user interrupts in wait - wreaks havoc with performance */ | 474 | rc = wait_for_response(ses->server, midQ); |
529 | wait_for_response(ses, midQ, timeout, 10 * HZ); | 475 | if (rc != 0) |
476 | goto out; | ||
530 | 477 | ||
531 | rc = sync_mid_result(midQ, ses->server); | 478 | rc = sync_mid_result(midQ, ses->server); |
532 | if (rc != 0) { | 479 | if (rc != 0) { |
@@ -604,7 +551,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
604 | { | 551 | { |
605 | int rc = 0; | 552 | int rc = 0; |
606 | unsigned int receive_len; | 553 | unsigned int receive_len; |
607 | unsigned long timeout; | ||
608 | struct mid_q_entry *midQ; | 554 | struct mid_q_entry *midQ; |
609 | 555 | ||
610 | if (ses == NULL) { | 556 | if (ses == NULL) { |
@@ -668,33 +614,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
668 | if (rc < 0) | 614 | if (rc < 0) |
669 | goto out; | 615 | goto out; |
670 | 616 | ||
671 | if (long_op == CIFS_STD_OP) | 617 | if (long_op == CIFS_ASYNC_OP) |
672 | timeout = 15 * HZ; | ||
673 | /* wait for 15 seconds or until woken up due to response arriving or | ||
674 | due to last connection to this server being unmounted */ | ||
675 | else if (long_op == CIFS_ASYNC_OP) | ||
676 | goto out; | ||
677 | else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */ | ||
678 | timeout = 180 * HZ; | ||
679 | else if (long_op == CIFS_LONG_OP) | ||
680 | timeout = 45 * HZ; /* should be greater than | ||
681 | servers oplock break timeout (about 43 seconds) */ | ||
682 | else if (long_op == CIFS_BLOCKING_OP) | ||
683 | timeout = 0x7FFFFFFF; /* large but no so large as to wrap */ | ||
684 | else { | ||
685 | cERROR(1, "unknown timeout flag %d", long_op); | ||
686 | rc = -EIO; | ||
687 | goto out; | 618 | goto out; |
688 | } | ||
689 | 619 | ||
690 | if (signal_pending(current)) { | 620 | rc = wait_for_response(ses->server, midQ); |
691 | /* if signal pending do not hold up user for full smb timeout | 621 | if (rc != 0) |
692 | but we still give response a chance to complete */ | 622 | goto out; |
693 | timeout = 2 * HZ; | ||
694 | } | ||
695 | |||
696 | /* No user interrupts in wait - wreaks havoc with performance */ | ||
697 | wait_for_response(ses, midQ, timeout, 10 * HZ); | ||
698 | 623 | ||
699 | rc = sync_mid_result(midQ, ses->server); | 624 | rc = sync_mid_result(midQ, ses->server); |
700 | if (rc != 0) { | 625 | if (rc != 0) { |
@@ -915,8 +840,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
915 | } | 840 | } |
916 | } | 841 | } |
917 | 842 | ||
918 | /* Wait 5 seconds for the response. */ | 843 | if (wait_for_response(ses->server, midQ) == 0) { |
919 | if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) { | ||
920 | /* We got the response - restart system call. */ | 844 | /* We got the response - restart system call. */ |
921 | rstart = 1; | 845 | rstart = 1; |
922 | } | 846 | } |