]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
smb: server: let recv_done() consistently call put_recvmsg/smb_direct_disconnect_rdma...
authorStefan Metzmacher <metze@samba.org>
Mon, 4 Aug 2025 12:15:52 +0000 (14:15 +0200)
committerSteve French <stfrench@microsoft.com>
Wed, 6 Aug 2025 19:09:57 +0000 (14:09 -0500)
We should call put_recvmsg() before smb_direct_disconnect_rdma_connection()
in order to call it before waking up the callers.

In all error cases we should call smb_direct_disconnect_rdma_connection()
in order to avoid stale connections.

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
Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
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 fac82e60ff805166722e4b28e1770729e1945131..cd8a92fe372b13cb589940c312a69689304283dd 100644 (file)
@@ -521,13 +521,13 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
        t = recvmsg->transport;
 
        if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
+               put_recvmsg(t, recvmsg);
                if (wc->status != IB_WC_WR_FLUSH_ERR) {
                        pr_err("Recv error. status='%s (%d)' opcode=%d\n",
                               ib_wc_status_msg(wc->status), wc->status,
                               wc->opcode);
                        smb_direct_disconnect_rdma_connection(t);
                }
-               put_recvmsg(t, recvmsg);
                return;
        }
 
@@ -542,6 +542,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
        case SMB_DIRECT_MSG_NEGOTIATE_REQ:
                if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) {
                        put_recvmsg(t, recvmsg);
+                       smb_direct_disconnect_rdma_connection(t);
                        return;
                }
                t->negotiation_requested = true;
@@ -549,7 +550,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                t->status = SMB_DIRECT_CS_CONNECTED;
                enqueue_reassembly(t, recvmsg, 0);
                wake_up_interruptible(&t->wait_status);
-               break;
+               return;
        case SMB_DIRECT_MSG_DATA_TRANSFER: {
                struct smb_direct_data_transfer *data_transfer =
                        (struct smb_direct_data_transfer *)recvmsg->packet;
@@ -559,6 +560,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                if (wc->byte_len <
                    offsetof(struct smb_direct_data_transfer, padding)) {
                        put_recvmsg(t, recvmsg);
+                       smb_direct_disconnect_rdma_connection(t);
                        return;
                }
 
@@ -567,6 +569,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                        if (wc->byte_len < sizeof(struct smb_direct_data_transfer) +
                            (u64)data_length) {
                                put_recvmsg(t, recvmsg);
+                               smb_direct_disconnect_rdma_connection(t);
                                return;
                        }
 
@@ -609,11 +612,16 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count))
                        mod_delayed_work(smb_direct_wq,
                                         &t->post_recv_credits_work, 0);
-               break;
+               return;
        }
-       default:
-               break;
        }
+
+       /*
+        * This is an internal error!
+        */
+       WARN_ON_ONCE(recvmsg->type != SMB_DIRECT_MSG_DATA_TRANSFER);
+       put_recvmsg(t, recvmsg);
+       smb_direct_disconnect_rdma_connection(t);
 }
 
 static int smb_direct_post_recv(struct smb_direct_transport *t,