]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb: server: queue post_recv_credits_work in put_recvmsg() and avoid count_avail_recvmsg
authorStefan Metzmacher <metze@samba.org>
Mon, 11 Aug 2025 16:23:03 +0000 (18:23 +0200)
committerSteve French <stfrench@microsoft.com>
Sun, 28 Sep 2025 23:29:52 +0000 (18:29 -0500)
This is basically what the client is doing in put_receive_buffer().

It means we don't need complicated work to maintain count_avail_recvmsg.

But we keep the logic to queue post_recv_credits_work if the
peer raises the requested credit_target and put_receive_buffer()
is not called.

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 67a0a2974dcbb82f517ad282a7d025f2bb892c84..6c34a271ae849d1ddbbfdb36b4dd833b5b672fe5 100644 (file)
@@ -96,7 +96,6 @@ struct smb_direct_transport {
 
        spinlock_t              receive_credit_lock;
        int                     recv_credits;
-       int                     count_avail_recvmsg;
        int                     recv_credit_target;
 
        atomic_t                send_credits;
@@ -183,13 +182,6 @@ static inline void
        return (void *)recvmsg->packet;
 }
 
-static inline bool is_receive_credit_post_required(int receive_credits,
-                                                  int avail_recvmsg_count)
-{
-       return receive_credits <= (smb_direct_receive_credit_max >> 3) &&
-               avail_recvmsg_count >= (receive_credits >> 2);
-}
-
 static struct
 smbdirect_recv_io *get_free_recvmsg(struct smb_direct_transport *t)
 {
@@ -223,6 +215,8 @@ static void put_recvmsg(struct smb_direct_transport *t,
        spin_lock(&sc->recv_io.free.lock);
        list_add(&recvmsg->list, &sc->recv_io.free.list);
        spin_unlock(&sc->recv_io.free.lock);
+
+       queue_work(smb_direct_wq, &t->post_recv_credits_work);
 }
 
 static void enqueue_reassembly(struct smb_direct_transport *t,
@@ -530,7 +524,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                struct smbdirect_data_transfer *data_transfer =
                        (struct smbdirect_data_transfer *)recvmsg->packet;
                u32 remaining_data_length, data_offset, data_length;
-               int avail_recvmsg_count, receive_credits;
+               int old_recv_credit_target;
 
                if (wc->byte_len <
                    offsetof(struct smbdirect_data_transfer, padding)) {
@@ -565,18 +559,13 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                                sc->recv_io.reassembly.full_packet_received = false;
                        else
                                sc->recv_io.reassembly.full_packet_received = true;
-
-                       spin_lock(&t->receive_credit_lock);
-                       receive_credits = --(t->recv_credits);
-                       avail_recvmsg_count = t->count_avail_recvmsg;
-                       spin_unlock(&t->receive_credit_lock);
-               } else {
-                       spin_lock(&t->receive_credit_lock);
-                       receive_credits = --(t->recv_credits);
-                       avail_recvmsg_count = ++(t->count_avail_recvmsg);
-                       spin_unlock(&t->receive_credit_lock);
                }
 
+               spin_lock(&t->receive_credit_lock);
+               t->recv_credits -= 1;
+               spin_unlock(&t->receive_credit_lock);
+
+               old_recv_credit_target = t->recv_credit_target;
                t->recv_credit_target =
                                le16_to_cpu(data_transfer->credits_requested);
                atomic_add(le16_to_cpu(data_transfer->credits_granted),
@@ -589,10 +578,10 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                if (atomic_read(&t->send_credits) > 0)
                        wake_up(&t->wait_send_credits);
 
-               if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count))
-                       queue_work(smb_direct_wq, &t->post_recv_credits_work);
-
                if (data_length) {
+                       if (t->recv_credit_target > old_recv_credit_target)
+                               queue_work(smb_direct_wq, &t->post_recv_credits_work);
+
                        enqueue_reassembly(t, recvmsg, (int)data_length);
                        wake_up(&sc->recv_io.reassembly.wait_queue);
                } else
@@ -750,15 +739,6 @@ again:
                sc->recv_io.reassembly.queue_length -= queue_removed;
                spin_unlock_irq(&sc->recv_io.reassembly.lock);
 
-               spin_lock(&st->receive_credit_lock);
-               st->count_avail_recvmsg += queue_removed;
-               if (is_receive_credit_post_required(st->recv_credits, st->count_avail_recvmsg)) {
-                       spin_unlock(&st->receive_credit_lock);
-                       queue_work(smb_direct_wq, &st->post_recv_credits_work);
-               } else {
-                       spin_unlock(&st->receive_credit_lock);
-               }
-
                sc->recv_io.reassembly.first_entry_offset = offset;
                ksmbd_debug(RDMA,
                            "returning to thread data_read=%d reassembly_data_length=%d first_entry_offset=%d\n",
@@ -810,7 +790,6 @@ static void smb_direct_post_recv_credits(struct work_struct *work)
 
        spin_lock(&t->receive_credit_lock);
        t->recv_credits += credits;
-       t->count_avail_recvmsg -= credits;
        spin_unlock(&t->receive_credit_lock);
 
        spin_lock(&t->lock_new_recv_credits);
@@ -1826,7 +1805,6 @@ static int smb_direct_init_params(struct smb_direct_transport *t,
        }
 
        t->recv_credits = 0;
-       t->count_avail_recvmsg = 0;
 
        sp->recv_credit_max = smb_direct_receive_credit_max;
        t->recv_credit_target = 10;
@@ -1914,7 +1892,6 @@ static int smb_direct_create_pools(struct smb_direct_transport *t)
                recvmsg->sge.length = 0;
                list_add(&recvmsg->list, &sc->recv_io.free.list);
        }
-       t->count_avail_recvmsg = sp->recv_credit_max;
 
        return 0;
 err: