]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb: client: send empty packets via send_immediate_work
authorStefan Metzmacher <metze@samba.org>
Fri, 15 Aug 2025 10:53:35 +0000 (12:53 +0200)
committerSteve French <stfrench@microsoft.com>
Sun, 28 Sep 2025 23:29:49 +0000 (18:29 -0500)
This is what the server already does and it makes
refactoring for common structures and functions much easier.

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

index b910d62d66c58409501470b8a4ff6f6131db285a..d53e39e91e1056968d7f14ddeb846e9b12aceb7f 100644 (file)
@@ -173,6 +173,7 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)
        disable_work(&sc->disconnect_work);
        disable_work(&sc->recv_io.posted.refill_work);
        disable_work(&info->mr_recovery_work);
+       disable_work(&info->send_immediate_work);
        disable_delayed_work(&info->idle_timer_work);
 
        switch (sc->status) {
@@ -569,8 +570,8 @@ static void smbd_post_send_credits(struct work_struct *work)
        /* Promptly send an immediate packet as defined in [MS-SMBD] 3.1.1.1 */
        if (atomic_read(&sc->recv_io.credits.count) <
                sc->recv_io.credits.target - 1) {
-               log_keep_alive(INFO, "send an empty message\n");
-               smbd_post_send_empty(info);
+               log_keep_alive(INFO, "schedule send of an empty message\n");
+               queue_work(info->workqueue, &info->send_immediate_work);
        }
 }
 
@@ -1455,6 +1456,19 @@ static void destroy_receive_buffers(struct smbd_connection *info)
                mempool_free(response, sc->recv_io.mem.pool);
 }
 
+static void send_immediate_empty_message(struct work_struct *work)
+{
+       struct smbd_connection *info =
+               container_of(work, struct smbd_connection, send_immediate_work);
+       struct smbdirect_socket *sc = &info->socket;
+
+       if (sc->status != SMBDIRECT_SOCKET_CONNECTED)
+               return;
+
+       log_keep_alive(INFO, "send an empty message\n");
+       smbd_post_send_empty(info);
+}
+
 /* Implement idle connection timer [MS-SMBD] 3.1.6.2 */
 static void idle_connection_timer(struct work_struct *work)
 {
@@ -1472,8 +1486,8 @@ static void idle_connection_timer(struct work_struct *work)
                return;
        }
 
-       log_keep_alive(INFO, "about to send an empty idle message\n");
-       smbd_post_send_empty(info);
+       log_keep_alive(INFO, "schedule send of empty idle message\n");
+       queue_work(info->workqueue, &info->send_immediate_work);
 
        /* Setup the next idle timeout work */
        queue_delayed_work(info->workqueue, &info->idle_timer_work,
@@ -1520,6 +1534,8 @@ void smbd_destroy(struct TCP_Server_Info *server)
 
        log_rdma_event(INFO, "cancelling idle timer\n");
        disable_delayed_work_sync(&info->idle_timer_work);
+       log_rdma_event(INFO, "cancelling send immediate work\n");
+       disable_work_sync(&info->send_immediate_work);
 
        /* It's not possible for upper layer to get to reassembly */
        log_rdma_event(INFO, "drain the reassembly queue\n");
@@ -1863,6 +1879,7 @@ static struct smbd_connection *_smbd_get_connection(
                goto allocate_cache_failed;
        }
 
+       INIT_WORK(&info->send_immediate_work, send_immediate_empty_message);
        INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer);
        queue_delayed_work(info->workqueue, &info->idle_timer_work,
                msecs_to_jiffies(sp->keepalive_interval_msec));
index 1bb9b9412685bd9e68359c52e7c52fc46efbe0f0..07c7fba2f340b9621e6b3db8d2fb304126f79137 100644 (file)
@@ -71,6 +71,7 @@ struct smbd_connection {
        wait_queue_head_t wait_for_mr_cleanup;
 
        struct workqueue_struct *workqueue;
+       struct work_struct send_immediate_work;
        struct delayed_work idle_timer_work;
 
        /* for debug purposes */