]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb: server: manage recv credits by counting posted recv_io and granted credits
authorStefan Metzmacher <metze@samba.org>
Thu, 14 Aug 2025 14:05:47 +0000 (16:05 +0200)
committerSteve French <stfrench@microsoft.com>
Sun, 28 Sep 2025 23:29:52 +0000 (18:29 -0500)
(At least for me) the logic maintaining the count of posted
recv_io messages and the count of granted credits is much
easier to understand.

From there we can easily calculate the number of new_credits we'll
grant to the peer in outgoing send_io messages.

This will simplify the move to common logic that can be
shared between client and server in the following patches.

Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/transport_rdma.c

index 283f06cf493851a45abaf2651dd7affe084c73d3..bd6d927e9656ac8d5c7e92120180015fbe6a07d5 100644 (file)
@@ -92,13 +92,10 @@ struct smb_direct_transport {
 
        struct smbdirect_socket socket;
 
-       spinlock_t              receive_credit_lock;
-       int                     recv_credits;
+       atomic_t                recv_credits;
        u16                     recv_credit_target;
 
-       spinlock_t              lock_new_recv_credits;
-       int                     new_recv_credits;
-
+       atomic_t                recv_posted;
        struct work_struct      post_recv_credits_work;
        struct work_struct      send_immediate_work;
 
@@ -309,9 +306,8 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
 
        sc->ib.dev = sc->rdma.cm_id->device;
 
-       spin_lock_init(&t->receive_credit_lock);
-
-       spin_lock_init(&t->lock_new_recv_credits);
+       atomic_set(&t->recv_posted, 0);
+       atomic_set(&t->recv_credits, 0);
 
        INIT_WORK(&t->post_recv_credits_work,
                  smb_direct_post_recv_credits);
@@ -552,9 +548,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                                sc->recv_io.reassembly.full_packet_received = true;
                }
 
-               spin_lock(&t->receive_credit_lock);
-               t->recv_credits -= 1;
-               spin_unlock(&t->receive_credit_lock);
+               atomic_dec(&t->recv_posted);
+               atomic_dec(&t->recv_credits);
 
                old_recv_credit_target = t->recv_credit_target;
                t->recv_credit_target =
@@ -758,14 +753,10 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
        struct smb_direct_transport *t = container_of(work,
                struct smb_direct_transport, post_recv_credits_work);
        struct smbdirect_recv_io *recvmsg;
-       int receive_credits, credits = 0;
+       int credits = 0;
        int ret;
 
-       spin_lock(&t->receive_credit_lock);
-       receive_credits = t->recv_credits;
-       spin_unlock(&t->receive_credit_lock);
-
-       if (receive_credits < t->recv_credit_target) {
+       if (atomic_read(&t->recv_credits) < t->recv_credit_target) {
                while (true) {
                        recvmsg = get_free_recvmsg(t);
                        if (!recvmsg)
@@ -780,17 +771,11 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
                                break;
                        }
                        credits++;
+
+                       atomic_inc(&t->recv_posted);
                }
        }
 
-       spin_lock(&t->receive_credit_lock);
-       t->recv_credits += credits;
-       spin_unlock(&t->receive_credit_lock);
-
-       spin_lock(&t->lock_new_recv_credits);
-       t->new_recv_credits += credits;
-       spin_unlock(&t->lock_new_recv_credits);
-
        if (credits)
                queue_work(smb_direct_wq, &t->send_immediate_work);
 }
@@ -837,11 +822,18 @@ static int manage_credits_prior_sending(struct smb_direct_transport *t)
 {
        int new_credits;
 
-       spin_lock(&t->lock_new_recv_credits);
-       new_credits = t->new_recv_credits;
-       t->new_recv_credits = 0;
-       spin_unlock(&t->lock_new_recv_credits);
+       if (atomic_read(&t->recv_credits) >= t->recv_credit_target)
+               return 0;
+
+       new_credits = atomic_read(&t->recv_posted);
+       if (new_credits == 0)
+               return 0;
 
+       new_credits -= atomic_read(&t->recv_credits);
+       if (new_credits <= 0)
+               return 0;
+
+       atomic_add(new_credits, &t->recv_credits);
        return new_credits;
 }
 
@@ -1824,11 +1816,8 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
                return -EINVAL;
        }
 
-       t->recv_credits = 0;
-
        sp->recv_credit_max = smb_direct_receive_credit_max;
        t->recv_credit_target = 1;
-       t->new_recv_credits = 0;
 
        sp->send_credit_target = smb_direct_send_credit_target;
        atomic_set(&sc->rw_io.credits.count, sc->rw_io.credits.max);