]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
smb: smbdirect: fix the logic in smbdirect_socket_destroy_sync() without an error
authorStefan Metzmacher <metze@samba.org>
Tue, 7 Apr 2026 14:46:29 +0000 (16:46 +0200)
committerSteve French <stfrench@microsoft.com>
Thu, 16 Apr 2026 02:58:24 +0000 (21:58 -0500)
If smbdirect_socket_destroy_sync() and sc->first_error was not set
we should set -ESHUTDOWN, that's a better condition
doing it only implicitly with the
sc->status < SMBDIRECT_SOCKET_DISCONNECTING check.

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: David Howells <dhowells@redhat.com>
Cc: Henrique Carvalho <henrique.carvalho@suse.com>
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/common/smbdirect/smbdirect_socket.c

index 4003753bea2619ea9242ed65f0a07ad88392ed97..9153e1dbf53d5532d128759ae3411bc85d62d9fe 100644 (file)
@@ -600,13 +600,20 @@ void smbdirect_socket_destroy_sync(struct smbdirect_socket *sc)
         */
        WARN_ON_ONCE(in_interrupt());
 
-       smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
-               "cancelling and disable disconnect_work\n");
-       disable_work_sync(&sc->disconnect_work);
+       /*
+        * First we try to disable the work
+        * without disable_work_sync() in a
+        * non blocking way, if it's already
+        * running it will be handles by
+        * disable_work_sync() below.
+        *
+        * Here we just want to make sure queue_work() in
+        * smbdirect_socket_schedule_cleanup_lvl()
+        * is a no-op.
+        */
+       disable_work(&sc->disconnect_work);
 
-       smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
-               "destroying rdma session\n");
-       if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING) {
+       if (!sc->first_error)
                /*
                 * SMBDIRECT_LOG_INFO is enough here
                 * as this is the typical case where
@@ -615,8 +622,15 @@ void smbdirect_socket_destroy_sync(struct smbdirect_socket *sc)
                smbdirect_socket_schedule_cleanup_lvl(sc,
                                                      SMBDIRECT_LOG_INFO,
                                                      -ESHUTDOWN);
+
+       smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+               "cancelling and disable disconnect_work\n");
+       disable_work_sync(&sc->disconnect_work);
+
+       smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
+               "destroying rdma session\n");
+       if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING)
                smbdirect_socket_cleanup_work(&sc->disconnect_work);
-       }
        if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED) {
                smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_INFO,
                        "wait for transport being disconnected\n");