aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2011-01-20 13:06:34 -0500
committerSteve French <sfrench@us.ibm.com>2011-01-20 13:06:34 -0500
commitfda3594362184383e73f0a2a5fa5b38ac0e04fd8 (patch)
treec196d4a5211044760debd89eec810053f0025e45 /fs/cifs
parentc74093b694998d30105d9904686da5e3576497c4 (diff)
[CIFS] cifs: reconnect unresponsive servers
If the server isn't responding to echoes, we don't want to leave tasks hung waiting for it to reply. At that point, we'll want to reconnect so that soft mounts can return an error to userspace quickly. If the client hasn't received a reply after a specified number of echo intervals, assume that the transport is down and attempt to reconnect the socket. The number of echo_intervals to wait before attempting to reconnect is tunable via a module parameter. Setting it to 0, means that the client will never attempt to reconnect. The default is 5. Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsfs.c6
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/connect.c21
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;
77module_param(cifs_max_pending, int, 0); 77module_param(cifs_max_pending, int, 0);
78MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " 78MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. "
79 "Default: 50 Range: 2 to 256"); 79 "Default: 50 Range: 2 to 256");
80 80unsigned short echo_retries = 5;
81module_param(echo_retries, ushort, 0644);
82MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and "
83 "reconnecting server. Default: 5. 0 means "
84 "never reconnect.");
81extern mempool_t *cifs_sm_req_poolp; 85extern mempool_t *cifs_sm_req_poolp;
82extern mempool_t *cifs_req_poolp; 86extern mempool_t *cifs_req_poolp;
83extern mempool_t *cifs_mid_poolp; 87extern 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 */
804GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ 804GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
805GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ 805GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
806 806
807/* reconnect after this many failed echo attempts */
808GLOBAL_EXTERN unsigned short echo_retries;
809
807void cifs_oplock_break(struct work_struct *work); 810void cifs_oplock_break(struct work_struct *work);
808void cifs_oplock_break_get(struct cifsFileInfo *cfile); 811void cifs_oplock_break_get(struct cifsFileInfo *cfile);
809void cifs_oplock_break_put(struct cifsFileInfo *cfile); 812void 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
423incomplete_rcv: 425incomplete_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);