]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:smb2_server: always try to grant the credits the client just consumed
authorStefan Metzmacher <metze@samba.org>
Wed, 28 Jan 2015 14:22:30 +0000 (15:22 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 2 Feb 2015 20:52:12 +0000 (21:52 +0100)
It turns out that the effective credits_requested is always at least 1,
even if the client sends credits_requested == 0.

This means the client is not able to reduce the amount of credits
itself.

Without this fix a client (e.g. Windows7) would reach the case
where it has been granted all credits it asked for.
When copying a large file with a lot of parallel requests,
all these requests have credits_requested == 0.
This means the amount of granted credits where reduced by each
request and only when the granted credits reached 0,
the server granted one credit to allow the client to go on.
The client might require more than one credit ([MS-SMB2] says
Windows clients require at least 4 credits) and freezes
with just 1 credit.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=9702

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
(similar to commit 1944c857e59922a2ebfc88a6a824a6ed9396f2d5)

source3/smbd/smb2_server.c

index f7798fadd750a4622e7816518d6e32055eea4abf..fb99f8d7882fd5202afb50cb7b7c7588a0bf7329 100644 (file)
@@ -777,6 +777,7 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
 
        cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
        credits_requested = SVAL(inhdr, SMB2_HDR_CREDIT);
+       credits_requested = MAX(credits_requested, 1);
        out_flags = IVAL(outhdr, SMB2_HDR_FLAGS);
        out_status = NT_STATUS(IVAL(outhdr, SMB2_HDR_STATUS));
 
@@ -795,7 +796,7 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
                 * credits on the final response.
                 */
                credits_granted = 0;
-       } else if (credits_requested > 0) {
+       } else {
                uint16_t additional_max = 0;
                uint16_t additional_credits = credits_requested - 1;
 
@@ -824,11 +825,6 @@ static void smb2_set_operation_credit(struct smbd_server_connection *sconn,
                additional_credits = MIN(additional_credits, additional_max);
 
                credits_granted = credit_charge + additional_credits;
-       } else if (sconn->smb2.credits_granted == 0) {
-               /*
-                * Make sure the client has always at least one credit
-                */
-               credits_granted = 1;
        }
 
        /*