[v2] Call echo service immediately after socket reconnect
diff mbox

Message ID 1477007544-4656-1-git-send-email-sprabhu@redhat.com
State New
Headers show

Commit Message

Sachin Prabhu Oct. 20, 2016, 11:52 p.m. UTC
Commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session reconnect
long after socket reconnect") changes the behaviour of the SMB2 echo
service and causes it to renegotiate after a socket reconnect. However
under default settings, the echo service could take up to 120 seconds to
be scheduled.

The patch forces the echo service to be called immediately resulting a
negotiate call being made immediately on reconnect.

Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
---
 fs/cifs/connect.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

Comments

Pavel Shilovsky Oct. 21, 2016, 1:33 a.m. UTC | #1
2016-10-20 16:52 GMT-07:00 Sachin Prabhu <sprabhu@redhat.com>:
> Commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session reconnect
> long after socket reconnect") changes the behaviour of the SMB2 echo
> service and causes it to renegotiate after a socket reconnect. However
> under default settings, the echo service could take up to 120 seconds to
> be scheduled.
>
> The patch forces the echo service to be called immediately resulting a
> negotiate call being made immediately on reconnect.
>
> Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
> ---
>  fs/cifs/connect.c | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index aab5227..4547aed 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -412,6 +412,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
>                 }
>         } while (server->tcpStatus == CifsNeedReconnect);
>
> +       if (server->tcpStatus == CifsNeedNegotiate)
> +               mod_delayed_work(cifsiod_wq, &server->echo, 0);
> +
>         return rc;
>  }
>
> @@ -421,17 +424,25 @@ cifs_echo_request(struct work_struct *work)
>         int rc;
>         struct TCP_Server_Info *server = container_of(work,
>                                         struct TCP_Server_Info, echo.work);
> -       unsigned long echo_interval = server->echo_interval;
> +       unsigned long echo_interval;
> +
> +       /*
> +        * If we need to renegotiate, set echo interval to zero to
> +        * immediately call echo service where we can renegotiate.
> +        */
> +       if (server->tcpStatus == CifsNeedNegotiate)
> +               echo_interval = 0;
> +       else
> +               echo_interval = server->echo_interval;
>
>         /*
> -        * We cannot send an echo if it is disabled or until the
> -        * NEGOTIATE_PROTOCOL request is done, which is indicated by
> -        * server->ops->need_neg() == true. Also, no need to ping if
> -        * we got a response recently.
> +        * We cannot send an echo if it is disabled.
> +        * Also, no need to ping if we got a response recently.
>          */
>
>         if (server->tcpStatus == CifsNeedReconnect ||
> -           server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
> +           server->tcpStatus == CifsExiting ||
> +           server->tcpStatus == CifsNew ||
>             (server->ops->can_echo && !server->ops->can_echo(server)) ||
>             time_before(jiffies, server->lstrp + echo_interval - HZ))
>                 goto requeue_echo;
> @@ -442,7 +453,7 @@ cifs_echo_request(struct work_struct *work)
>                          server->hostname);
>
>  requeue_echo:
> -       queue_delayed_work(cifsiod_wq, &server->echo, echo_interval);
> +       queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
>  }
>
>  static bool
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Steve French Oct. 21, 2016, 3:40 a.m. UTC | #2
merged into cifs-2.6.git for-next

On Thu, Oct 20, 2016 at 8:33 PM, Pavel Shilovsky <piastryyy@gmail.com> wrote:
> 2016-10-20 16:52 GMT-07:00 Sachin Prabhu <sprabhu@redhat.com>:
>> Commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session reconnect
>> long after socket reconnect") changes the behaviour of the SMB2 echo
>> service and causes it to renegotiate after a socket reconnect. However
>> under default settings, the echo service could take up to 120 seconds to
>> be scheduled.
>>
>> The patch forces the echo service to be called immediately resulting a
>> negotiate call being made immediately on reconnect.
>>
>> Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
>> ---
>>  fs/cifs/connect.c | 25 ++++++++++++++++++-------
>>  1 file changed, 18 insertions(+), 7 deletions(-)
>>
>> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
>> index aab5227..4547aed 100644
>> --- a/fs/cifs/connect.c
>> +++ b/fs/cifs/connect.c
>> @@ -412,6 +412,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
>>                 }
>>         } while (server->tcpStatus == CifsNeedReconnect);
>>
>> +       if (server->tcpStatus == CifsNeedNegotiate)
>> +               mod_delayed_work(cifsiod_wq, &server->echo, 0);
>> +
>>         return rc;
>>  }
>>
>> @@ -421,17 +424,25 @@ cifs_echo_request(struct work_struct *work)
>>         int rc;
>>         struct TCP_Server_Info *server = container_of(work,
>>                                         struct TCP_Server_Info, echo.work);
>> -       unsigned long echo_interval = server->echo_interval;
>> +       unsigned long echo_interval;
>> +
>> +       /*
>> +        * If we need to renegotiate, set echo interval to zero to
>> +        * immediately call echo service where we can renegotiate.
>> +        */
>> +       if (server->tcpStatus == CifsNeedNegotiate)
>> +               echo_interval = 0;
>> +       else
>> +               echo_interval = server->echo_interval;
>>
>>         /*
>> -        * We cannot send an echo if it is disabled or until the
>> -        * NEGOTIATE_PROTOCOL request is done, which is indicated by
>> -        * server->ops->need_neg() == true. Also, no need to ping if
>> -        * we got a response recently.
>> +        * We cannot send an echo if it is disabled.
>> +        * Also, no need to ping if we got a response recently.
>>          */
>>
>>         if (server->tcpStatus == CifsNeedReconnect ||
>> -           server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
>> +           server->tcpStatus == CifsExiting ||
>> +           server->tcpStatus == CifsNew ||
>>             (server->ops->can_echo && !server->ops->can_echo(server)) ||
>>             time_before(jiffies, server->lstrp + echo_interval - HZ))
>>                 goto requeue_echo;
>> @@ -442,7 +453,7 @@ cifs_echo_request(struct work_struct *work)
>>                          server->hostname);
>>
>>  requeue_echo:
>> -       queue_delayed_work(cifsiod_wq, &server->echo, echo_interval);
>> +       queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
>>  }
>>
>>  static bool
>> --
>> 2.7.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
>
> --
> Best regards,
> Pavel Shilovsky
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jonathan Liu April 15, 2017, 3:38 p.m. UTC | #3
Hi Sachin,

On 21 October 2016 at 10:52, Sachin Prabhu <sprabhu@redhat.com> wrote:
>
> Commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session reconnect
> long after socket reconnect") changes the behaviour of the SMB2 echo
> service and causes it to renegotiate after a socket reconnect. However
> under default settings, the echo service could take up to 120 seconds to
> be scheduled.
>
> The patch forces the echo service to be called immediately resulting a
> negotiate call being made immediately on reconnect.
>
> Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>

This commit is causing a flood of connections to Samba server as well
as high server CPU load when the Samba is restarted while CIFS share
is mounted on the client. This can cause the Samba server to become
slow or unresponsive resulting in denial of service to other users
connected to the Samba server.

Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=194531

Could you please have a look?

Thanks.

Regards,
Jonathan
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pavel Shilovsky April 15, 2017, 4:06 p.m. UTC | #4
2017-04-15 8:38 GMT-07:00 Jonathan Liu <net147@gmail.com>:
> Hi Sachin,
>
> On 21 October 2016 at 10:52, Sachin Prabhu <sprabhu@redhat.com> wrote:
>>
>> Commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session reconnect
>> long after socket reconnect") changes the behaviour of the SMB2 echo
>> service and causes it to renegotiate after a socket reconnect. However
>> under default settings, the echo service could take up to 120 seconds to
>> be scheduled.
>>
>> The patch forces the echo service to be called immediately resulting a
>> negotiate call being made immediately on reconnect.
>>
>> Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
>> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
>
> This commit is causing a flood of connections to Samba server as well
> as high server CPU load when the Samba is restarted while CIFS share
> is mounted on the client. This can cause the Samba server to become
> slow or unresponsive resulting in denial of service to other users
> connected to the Samba server.
>
> Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=194531
>
> Could you please have a look?
>
> Thanks.
>
> Regards,
> Jonathan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Hi Jonathan,

Thanks for reporting this.

It seems like we need to make CIFSSMBEcho() call as noop in case of
(server->tcpStatus == CifsNeedNegotiate) as we already did for
SMB2_echo().

--
Best regards,
Pavel Shilovsky
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sachin Prabhu April 16, 2017, 7:43 p.m. UTC | #5
On Sun, 2017-04-16 at 01:38 +1000, Jonathan Liu wrote:
> Hi Sachin,
> 
> On 21 October 2016 at 10:52, Sachin Prabhu <sprabhu@redhat.com>
> wrote:
> > 
> > Commit 4fcd1813e640 ("Fix reconnect to not defer smb3 session
> > reconnect
> > long after socket reconnect") changes the behaviour of the SMB2
> > echo
> > service and causes it to renegotiate after a socket reconnect.
> > However
> > under default settings, the echo service could take up to 120
> > seconds to
> > be scheduled.
> > 
> > The patch forces the echo service to be called immediately
> > resulting a
> > negotiate call being made immediately on reconnect.
> > 
> > Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
> > Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
> 
> This commit is causing a flood of connections to Samba server as well
> as high server CPU load when the Samba is restarted while CIFS share
> is mounted on the client. This can cause the Samba server to become
> slow or unresponsive resulting in denial of service to other users
> connected to the Samba server.
> 
> Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=194531
> 
> Could you please have a look?
> 
> Thanks.
> 
> Regards,
> Jonathan

Hello Jonathan,

Thanks for bringing this to my attention. I've posted a patch to the
list. I've tested it out with the reproducer. Can you please test it
out  in your setup and let me know if it works for you.

Sachin Prabhu

--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index aab5227..4547aed 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -412,6 +412,9 @@  cifs_reconnect(struct TCP_Server_Info *server)
 		}
 	} while (server->tcpStatus == CifsNeedReconnect);
 
+	if (server->tcpStatus == CifsNeedNegotiate)
+		mod_delayed_work(cifsiod_wq, &server->echo, 0);
+
 	return rc;
 }
 
@@ -421,17 +424,25 @@  cifs_echo_request(struct work_struct *work)
 	int rc;
 	struct TCP_Server_Info *server = container_of(work,
 					struct TCP_Server_Info, echo.work);
-	unsigned long echo_interval = server->echo_interval;
+	unsigned long echo_interval;
+
+	/*
+	 * If we need to renegotiate, set echo interval to zero to
+	 * immediately call echo service where we can renegotiate.
+	 */
+	if (server->tcpStatus == CifsNeedNegotiate)
+		echo_interval = 0;
+	else
+		echo_interval = server->echo_interval;
 
 	/*
-	 * We cannot send an echo if it is disabled or until the
-	 * NEGOTIATE_PROTOCOL request is done, which is indicated by
-	 * server->ops->need_neg() == true. Also, no need to ping if
-	 * we got a response recently.
+	 * We cannot send an echo if it is disabled.
+	 * Also, no need to ping if we got a response recently.
 	 */
 
 	if (server->tcpStatus == CifsNeedReconnect ||
-	    server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
+	    server->tcpStatus == CifsExiting ||
+	    server->tcpStatus == CifsNew ||
 	    (server->ops->can_echo && !server->ops->can_echo(server)) ||
 	    time_before(jiffies, server->lstrp + echo_interval - HZ))
 		goto requeue_echo;
@@ -442,7 +453,7 @@  cifs_echo_request(struct work_struct *work)
 			 server->hostname);
 
 requeue_echo:
-	queue_delayed_work(cifsiod_wq, &server->echo, echo_interval);
+	queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
 }
 
 static bool