]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
smb: client: let recv_done() queue a refill when the peer is low on credits
authorStefan Metzmacher <metze@samba.org>
Thu, 22 Jan 2026 17:16:49 +0000 (18:16 +0100)
committerSteve French <stfrench@microsoft.com>
Sun, 8 Feb 2026 23:12:57 +0000 (17:12 -0600)
In captures I saw that Windows was granting 191 credits in a batch
when its peer posted a lot of messages. We are asking for a
credit target of 255 and 191 is 252*3/4.

So we also use that logic in order to fill the
recv buffers available to the peer.

Fixes: 02548c477a90 ("smb: client: queue post_recv_credits_work also if the peer raises the credit target")
Cc: <stable@vger.kernel.org> # 6.18.x
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/smbdirect.c

index 6679abbb9797c0fdb615cee89b6dfdf2ee2f8e27..61693b4a83fcee5c8b4a13b056b4002ce6878837 100644 (file)
@@ -663,6 +663,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
        struct smbdirect_socket *sc = response->socket;
        struct smbdirect_socket_parameters *sp = &sc->parameters;
+       int current_recv_credits;
        u16 old_recv_credit_target;
        u32 data_offset = 0;
        u32 data_length = 0;
@@ -747,7 +748,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                }
 
                atomic_dec(&sc->recv_io.posted.count);
-               atomic_dec(&sc->recv_io.credits.count);
+               current_recv_credits = atomic_dec_return(&sc->recv_io.credits.count);
+
                old_recv_credit_target = sc->recv_io.credits.target;
                sc->recv_io.credits.target =
                        le16_to_cpu(data_transfer->credits_requested);
@@ -783,7 +785,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                 * reassembly queue and wake up the reading thread
                 */
                if (data_length) {
-                       if (sc->recv_io.credits.target > old_recv_credit_target)
+                       if (current_recv_credits <= (sc->recv_io.credits.target / 4) ||
+                           sc->recv_io.credits.target > old_recv_credit_target)
                                queue_work(sc->workqueue, &sc->recv_io.posted.refill_work);
 
                        enqueue_reassembly(sc, response, data_length);