cifs: set up recurring workqueue job to do SMB echo requests
Jeff Layton [Tue, 11 Jan 2011 12:24:23 +0000 (07:24 -0500)]
Reviewed-by: Suresh Jayaraman <sjayaraman@suse.de>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

fs/cifs/cifsglob.h
fs/cifs/connect.c

index 4de7375..9c728dd 100644 (file)
@@ -218,6 +218,7 @@ struct TCP_Server_Info {
        bool    sec_kerberosu2u;        /* supports U2U Kerberos */
        bool    sec_ntlmssp;            /* supports NTLMSSP */
        bool session_estab; /* mark when very first sess is established */
+       struct delayed_work     echo; /* echo ping workqueue job */
 #ifdef CONFIG_CIFS_FSCACHE
        struct fscache_cookie   *fscache; /* client index cache cookie */
 #endif
index aa66de1..f38ca08 100644 (file)
@@ -52,6 +52,9 @@
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
 
+/* SMB echo "timeout" -- FIXME: tunable? */
+#define SMB_ECHO_INTERVAL (60 * HZ)
+
 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
                         unsigned char *p24);
 
@@ -333,6 +336,26 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
 
 }
 
+static void
+cifs_echo_request(struct work_struct *work)
+{
+       int rc;
+       struct TCP_Server_Info *server = container_of(work,
+                                       struct TCP_Server_Info, echo.work);
+
+       /* no need to ping if we got a response recently */
+       if (time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
+               goto requeue_echo;
+
+       rc = CIFSSMBEcho(server);
+       if (rc)
+               cFYI(1, "Unable to send echo request to server: %s",
+                       server->hostname);
+
+requeue_echo:
+       queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
+}
+
 static int
 cifs_demultiplex_thread(struct TCP_Server_Info *server)
 {
@@ -1571,6 +1594,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
        list_del_init(&server->tcp_ses_list);
        spin_unlock(&cifs_tcp_ses_lock);
 
+       cancel_delayed_work_sync(&server->echo);
+
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
        spin_unlock(&GlobalMid_Lock);
@@ -1662,6 +1687,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        tcp_ses->sequence_number = 0;
        INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
        INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
+       INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
 
        /*
         * at this point we are the only ones with the pointer
@@ -1710,6 +1736,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 
        cifs_fscache_get_client_cookie(tcp_ses);
 
+       /* queue echo request delayed work */
+       queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL);
+
        return tcp_ses;
 
 out_err_crypto_release: