diff options
-rw-r--r-- | fs/cifs/cifsfs.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/connect.c | 21 |
3 files changed, 25 insertions, 5 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index d9f652a522a6..99d777a03dd0 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -77,7 +77,11 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ; | |||
77 | module_param(cifs_max_pending, int, 0); | 77 | module_param(cifs_max_pending, int, 0); |
78 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " | 78 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " |
79 | "Default: 50 Range: 2 to 256"); | 79 | "Default: 50 Range: 2 to 256"); |
80 | 80 | unsigned short echo_retries = 5; | |
81 | module_param(echo_retries, ushort, 0644); | ||
82 | MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " | ||
83 | "reconnecting server. Default: 5. 0 means " | ||
84 | "never reconnect."); | ||
81 | extern mempool_t *cifs_sm_req_poolp; | 85 | extern mempool_t *cifs_sm_req_poolp; |
82 | extern mempool_t *cifs_req_poolp; | 86 | extern mempool_t *cifs_req_poolp; |
83 | extern mempool_t *cifs_mid_poolp; | 87 | extern mempool_t *cifs_mid_poolp; |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 9c728dd5b146..7040abc638fa 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -804,6 +804,9 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ | |||
804 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ | 804 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ |
805 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ | 805 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ |
806 | 806 | ||
807 | /* reconnect after this many failed echo attempts */ | ||
808 | GLOBAL_EXTERN unsigned short echo_retries; | ||
809 | |||
807 | void cifs_oplock_break(struct work_struct *work); | 810 | void cifs_oplock_break(struct work_struct *work); |
808 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); | 811 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); |
809 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); | 812 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f38ca084c9d2..f5d7b59a3553 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -186,6 +186,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
186 | kfree(server->session_key.response); | 186 | kfree(server->session_key.response); |
187 | server->session_key.response = NULL; | 187 | server->session_key.response = NULL; |
188 | server->session_key.len = 0; | 188 | server->session_key.len = 0; |
189 | server->lstrp = jiffies; | ||
189 | mutex_unlock(&server->srv_mutex); | 190 | mutex_unlock(&server->srv_mutex); |
190 | 191 | ||
191 | /* mark submitted MIDs for retry and issue callback */ | 192 | /* mark submitted MIDs for retry and issue callback */ |
@@ -420,7 +421,20 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
420 | smb_msg.msg_control = NULL; | 421 | smb_msg.msg_control = NULL; |
421 | smb_msg.msg_controllen = 0; | 422 | smb_msg.msg_controllen = 0; |
422 | pdu_length = 4; /* enough to get RFC1001 header */ | 423 | pdu_length = 4; /* enough to get RFC1001 header */ |
424 | |||
423 | incomplete_rcv: | 425 | incomplete_rcv: |
426 | if (echo_retries > 0 && | ||
427 | time_after(jiffies, server->lstrp + | ||
428 | (echo_retries * SMB_ECHO_INTERVAL))) { | ||
429 | cERROR(1, "Server %s has not responded in %d seconds. " | ||
430 | "Reconnecting...", server->hostname, | ||
431 | (echo_retries * SMB_ECHO_INTERVAL / HZ)); | ||
432 | cifs_reconnect(server); | ||
433 | csocket = server->ssocket; | ||
434 | wake_up(&server->response_q); | ||
435 | continue; | ||
436 | } | ||
437 | |||
424 | length = | 438 | length = |
425 | kernel_recvmsg(csocket, &smb_msg, | 439 | kernel_recvmsg(csocket, &smb_msg, |
426 | &iov, 1, pdu_length, 0 /* BB other flags? */); | 440 | &iov, 1, pdu_length, 0 /* BB other flags? */); |
@@ -581,6 +595,8 @@ incomplete_rcv: | |||
581 | } | 595 | } |
582 | 596 | ||
583 | mid_entry = NULL; | 597 | mid_entry = NULL; |
598 | server->lstrp = jiffies; | ||
599 | |||
584 | spin_lock(&GlobalMid_Lock); | 600 | spin_lock(&GlobalMid_Lock); |
585 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { | 601 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
586 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 602 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
@@ -629,10 +645,6 @@ multi_t2_fnd: | |||
629 | #ifdef CONFIG_CIFS_STATS2 | 645 | #ifdef CONFIG_CIFS_STATS2 |
630 | mid_entry->when_received = jiffies; | 646 | mid_entry->when_received = jiffies; |
631 | #endif | 647 | #endif |
632 | /* so we do not time out requests to server | ||
633 | which is still responding (since server could | ||
634 | be busy but not dead) */ | ||
635 | server->lstrp = jiffies; | ||
636 | break; | 648 | break; |
637 | } | 649 | } |
638 | mid_entry = NULL; | 650 | mid_entry = NULL; |
@@ -1685,6 +1697,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1685 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); | 1697 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); |
1686 | tcp_ses->session_estab = false; | 1698 | tcp_ses->session_estab = false; |
1687 | tcp_ses->sequence_number = 0; | 1699 | tcp_ses->sequence_number = 0; |
1700 | tcp_ses->lstrp = jiffies; | ||
1688 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); | 1701 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); |
1689 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); | 1702 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); |
1690 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); | 1703 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); |