Interop Issue: SMB2+ async replies, and the kernel, Samba side fix enclosed.
diff mbox

Message ID CAKywueRePEMq7d2bYDZN48_esZrx0P2FofrDDxJ62RtQtX1Xww@mail.gmail.com
State New
Headers show

Commit Message

Pavel Shilovsky Feb. 27, 2016, 9:31 a.m. UTC
2016-02-27 12:11 GMT+03:00 Pavel Shilovsky <pshilovsky@samba.org>:
> 2016-02-23 15:55 GMT+03:00 Ira Cooper <ira@wakeful.net>:
>>
>> If the server sends an interim response, then the real response, the real
>> response, is handled by standard_receive3() in the kernel, instead of the
>> proper function, and this causes a disconnect.  If there isn't a
>> disconnect, I believe the reply will just be discarded if I understand the
>> code correctly.  (That is a big if here ;) )
>>
>> I've written a patch for Samba to stop sending interim replies on
>> SMB2_READ
>> and SMB2_WRITE, when non-compounded to stop the impact of this issue.  We
>> may want to add SMB2_CREATE to the list of ops we don't send async replies
>> for non-compounded, but I'm not sold either way, I know we CAN go async
>> there!  I want some opinions here.
>>
>> This is not hidden behind a flag because compatibility issues that don't
>> impact protocol correctness usually aren't.
>>
>> Setting req->async_te = talloc_new(NULL); is just ugly, though it works.
>> If you have a cleaner approach, I welcome it.
>>
>> I request you please ASK me before pushing this one, yes, that means you
>> jra!
>>
>> For those interested in reproduction: I'd suggest using a server that's
>> rebuilt with a lower timeout set in smb2_read.c, though we've hit it with
>> vfs_glusterfs straight up, in our testing.
>>
>> Thanks,
>>
>> -Ira / ira@(samba.org|redhat.com|wakeful.net)
>
>
>
> Thank you for catching this!
>
> It is the issue in the kernel client - a check for interim responses is
> missed for SMB2_READ command. I created a patch that should fix the problem.
>
> Could you please test it?
>
> --
> Best regards,
> Pavel Shilovsky

CC'ing @samba-technical.

Sorry for the spam.

Comments

Shirish Pargaonkar Feb. 27, 2016, 1:50 p.m. UTC | #1
Pavel, briefly tested this, it looks good. No error (messages) logged.

Tested-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>

On Sat, Feb 27, 2016 at 3:31 AM, Pavel Shilovsky <piastryyy@gmail.com> wrote:
> 2016-02-27 12:11 GMT+03:00 Pavel Shilovsky <pshilovsky@samba.org>:
>> 2016-02-23 15:55 GMT+03:00 Ira Cooper <ira@wakeful.net>:
>>>
>>> If the server sends an interim response, then the real response, the real
>>> response, is handled by standard_receive3() in the kernel, instead of the
>>> proper function, and this causes a disconnect.  If there isn't a
>>> disconnect, I believe the reply will just be discarded if I understand the
>>> code correctly.  (That is a big if here ;) )
>>>
>>> I've written a patch for Samba to stop sending interim replies on
>>> SMB2_READ
>>> and SMB2_WRITE, when non-compounded to stop the impact of this issue.  We
>>> may want to add SMB2_CREATE to the list of ops we don't send async replies
>>> for non-compounded, but I'm not sold either way, I know we CAN go async
>>> there!  I want some opinions here.
>>>
>>> This is not hidden behind a flag because compatibility issues that don't
>>> impact protocol correctness usually aren't.
>>>
>>> Setting req->async_te = talloc_new(NULL); is just ugly, though it works.
>>> If you have a cleaner approach, I welcome it.
>>>
>>> I request you please ASK me before pushing this one, yes, that means you
>>> jra!
>>>
>>> For those interested in reproduction: I'd suggest using a server that's
>>> rebuilt with a lower timeout set in smb2_read.c, though we've hit it with
>>> vfs_glusterfs straight up, in our testing.
>>>
>>> Thanks,
>>>
>>> -Ira / ira@(samba.org|redhat.com|wakeful.net)
>>
>>
>>
>> Thank you for catching this!
>>
>> It is the issue in the kernel client - a check for interim responses is
>> missed for SMB2_READ command. I created a patch that should fix the problem.
>>
>> Could you please test it?
>>
>> --
>> Best regards,
>> Pavel Shilovsky
>
> CC'ing @samba-technical.
>
> Sorry for the spam.
>
> --
> 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
Pavel Shilovsky Feb. 28, 2016, 6:22 a.m. UTC | #2
2016-02-27 16:50 GMT+03:00 Shirish Pargaonkar <shirishpargaonkar@gmail.com>:
> Pavel, briefly tested this, it looks good. No error (messages) logged.
>
> Tested-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>

Thanks!
Steve French Feb. 29, 2016, 4:17 a.m. UTC | #3
merged into cifs-2.6.git

Added Shirish's tested-by and cc: stable

Let me know if any objections to going to stable etc

On Sun, Feb 28, 2016 at 12:22 AM, Pavel Shilovsky <piastryyy@gmail.com> wrote:
> 2016-02-27 16:50 GMT+03:00 Shirish Pargaonkar <shirishpargaonkar@gmail.com>:
>> Pavel, briefly tested this, it looks good. No error (messages) logged.
>>
>> Tested-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
>
> Thanks!
>
> --
> 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

Patch
diff mbox

From 09904bf0c6a1ecc7f61d4755db33b762b53176d6 Mon Sep 17 00:00:00 2001
From: Pavel Shilovsky <pshilovsky@samba.org>
Date: Sat, 27 Feb 2016 11:58:18 +0300
Subject: [PATCH] CIFS: Fix SMB2+ interim response processing for read requests

For interim responses we only need to parse a header and update
a number credits. Now it is done for all SMB2+ command except
SMB2_READ which is wrong. Fix this by adding such processing.

Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
---
 fs/cifs/cifssmb.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 90b4f9f..76fcb50 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1396,11 +1396,10 @@  openRetry:
  * current bigbuf.
  */
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+discard_remaining_data(struct TCP_Server_Info *server)
 {
 	unsigned int rfclen = get_rfc1002_length(server->smallbuf);
 	int remaining = rfclen + 4 - server->total_read;
-	struct cifs_readdata *rdata = mid->callback_data;
 
 	while (remaining > 0) {
 		int length;
@@ -1414,10 +1413,20 @@  cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 		remaining -= length;
 	}
 
-	dequeue_mid(mid, rdata->result);
 	return 0;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+	int length;
+	struct cifs_readdata *rdata = mid->callback_data;
+
+	length = discard_remaining_data(server);
+	dequeue_mid(mid, rdata->result);
+	return length;
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1446,6 +1455,12 @@  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 		return length;
 	server->total_read += length;
 
+	if (server->ops->is_status_pending &&
+	    server->ops->is_status_pending(buf, server, 0)) {
+		discard_remaining_data(server);
+		return -1;
+	}
+
 	/* Was the SMB read successful? */
 	rdata->result = server->ops->map_error(buf, false);
 	if (rdata->result != 0) {
-- 
2.1.4