]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
smb: smbdirect: introduce smbdirect_socket_schedule_cleanup[{_lvl,_status}]()
authorStefan Metzmacher <metze@samba.org>
Tue, 26 Aug 2025 15:25:24 +0000 (17:25 +0200)
committerSteve French <stfrench@microsoft.com>
Thu, 16 Apr 2026 02:58:18 +0000 (21:58 -0500)
smbdirect_socket_schedule_cleanup() is more
or less copy of smbd_disconnect_rdma_connection() and
smb_direct_disconnect_rdma_connection(). It will replace
them in the next steps.

A difference is that the location of the first error is logged,
which makes it easier to analyze problems.

And also disable any complex work from recv_io objects,
currently these are not used and the work is always
disabled anyway, but this prepares future changes.

It also gets an explicit error passed
in instead of hardcoding -ECONNABORTED.

Beside the main smbdirect_socket_schedule_cleanup()
there are some special additions:
- smbdirect_socket_schedule_cleanup_lvl(),
  will be used for cases where we don't want
  a log message with SMBDIRECT_LOG_ERR.

- smbdirect_socket_schedule_cleanup_status(),
  will be used to specify the log level together
  with a direct final status, for the
  RDMA_CM_EVENT_DEVICE_REMOVAL and RDMA_CM_EVENT_DISCONNECTED
  cases where we need to avoid SMBDIRECT_SOCKET_DISCONNECTING
  and rdma_disconnect() in smbdirect_socket_cleanup_work().

With this we're also able to define a default
for __SMBDIRECT_SOCKET_DISCONNECT() just using:
smbdirect_socket_schedule_cleanup(__sc, -ECONNABORTED)

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: 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/common/smbdirect/smbdirect_internal.h
fs/smb/common/smbdirect/smbdirect_socket.c
fs/smb/common/smbdirect/smbdirect_socket.h

index e593eee0648193ebae7ce92f8b428faf8d9652d1..c946e53f94cd4281b95927b5b9ae4c617430e075 100644 (file)
 #include "smbdirect_pdu.h"
 #include "smbdirect_socket.h"
 
+static void __smbdirect_socket_schedule_cleanup(struct smbdirect_socket *sc,
+                                               const char *macro_name,
+                                               unsigned int lvl,
+                                               const char *func,
+                                               unsigned int line,
+                                               int error,
+                                               enum smbdirect_socket_status *force_status);
+#define smbdirect_socket_schedule_cleanup(__sc, __error) \
+       __smbdirect_socket_schedule_cleanup(__sc, \
+               "smbdirect_socket_schedule_cleanup", SMBDIRECT_LOG_ERR, \
+               __func__, __LINE__, __error, NULL)
+#define smbdirect_socket_schedule_cleanup_lvl(__sc, __lvl, __error) \
+       __smbdirect_socket_schedule_cleanup(__sc, \
+               "smbdirect_socket_schedule_cleanup_lvl", __lvl, \
+               __func__, __LINE__, __error, NULL)
+#define smbdirect_socket_schedule_cleanup_status(__sc, __lvl, __error, __status) do { \
+       enum smbdirect_socket_status __force_status = __status; \
+       __smbdirect_socket_schedule_cleanup(__sc, \
+               "smbdirect_socket_schedule_cleanup_status", __lvl, \
+               __func__, __LINE__, __error, &__force_status); \
+} while (0)
+
 #endif /* __FS_SMB_COMMON_SMBDIRECT_INTERNAL_H__ */
index a851b874b8193d38372c7321cc39f243757026e3..ba7e3ac32d920c1160a73e1b8c6a3e63e19dbbd9 100644 (file)
@@ -67,6 +67,101 @@ static void smbdirect_socket_wake_up_all(struct smbdirect_socket *sc)
        wake_up_all(&sc->mr_io.cleanup.wait_queue);
 }
 
+__maybe_unused /* this is temporary while this file is included in others */
+static void __smbdirect_socket_schedule_cleanup(struct smbdirect_socket *sc,
+                                               const char *macro_name,
+                                               unsigned int lvl,
+                                               const char *func,
+                                               unsigned int line,
+                                               int error,
+                                               enum smbdirect_socket_status *force_status)
+{
+       bool was_first = false;
+
+       if (!sc->first_error) {
+               ___smbdirect_log_generic(sc, func, line,
+                       lvl,
+                       SMBDIRECT_LOG_RDMA_EVENT,
+                       "%s(%1pe%s%s) called from %s in line=%u status=%s\n",
+                       macro_name,
+                       SMBDIRECT_DEBUG_ERR_PTR(error),
+                       force_status ? ", " : "",
+                       force_status ? smbdirect_socket_status_string(*force_status) : "",
+                       func, line,
+                       smbdirect_socket_status_string(sc->status));
+               if (error)
+                       sc->first_error = error;
+               else
+                       sc->first_error = -ECONNABORTED;
+               was_first = true;
+       }
+
+       /*
+        * make sure other work (than disconnect_work)
+        * is not queued again but here we don't block and avoid
+        * disable[_delayed]_work_sync()
+        */
+       disable_work(&sc->connect.work);
+       disable_work(&sc->recv_io.posted.refill_work);
+       disable_work(&sc->mr_io.recovery_work);
+       disable_work(&sc->idle.immediate_work);
+       disable_delayed_work(&sc->idle.timer_work);
+
+       switch (sc->status) {
+       case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
+       case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
+       case SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED:
+       case SMBDIRECT_SOCKET_NEGOTIATE_FAILED:
+       case SMBDIRECT_SOCKET_ERROR:
+       case SMBDIRECT_SOCKET_DISCONNECTING:
+       case SMBDIRECT_SOCKET_DISCONNECTED:
+       case SMBDIRECT_SOCKET_DESTROYED:
+               /*
+                * Keep the current error status
+                */
+               break;
+
+       case SMBDIRECT_SOCKET_RESOLVE_ADDR_NEEDED:
+       case SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING:
+               sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED;
+               break;
+
+       case SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED:
+       case SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING:
+               sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED;
+               break;
+
+       case SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED:
+       case SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING:
+               sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED;
+               break;
+
+       case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
+       case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
+               sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
+               break;
+
+       case SMBDIRECT_SOCKET_CREATED:
+               sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
+               break;
+
+       case SMBDIRECT_SOCKET_CONNECTED:
+               sc->status = SMBDIRECT_SOCKET_ERROR;
+               break;
+       }
+
+       if (force_status && (was_first || *force_status > sc->status))
+               sc->status = *force_status;
+
+       /*
+        * Wake up all waiters in all wait queues
+        * in order to notice the broken connection.
+        */
+       smbdirect_socket_wake_up_all(sc);
+
+       queue_work(sc->workqueue, &sc->disconnect_work);
+}
+
 static void smbdirect_socket_cleanup_work(struct work_struct *work)
 {
        struct smbdirect_socket *sc =
index 22184e53d445ff2c5915a8f1e4db532941e4226f..44506fc5cb92fe6cc158b3c407ad10ced0d5009d 100644 (file)
@@ -602,6 +602,11 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
 #define SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status) \
        __SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, /* nothing */)
 
+#ifndef __SMBDIRECT_SOCKET_DISCONNECT
+#define __SMBDIRECT_SOCKET_DISCONNECT(__sc) \
+               smbdirect_socket_schedule_cleanup(__sc, -ECONNABORTED)
+#endif /* ! __SMBDIRECT_SOCKET_DISCONNECT */
+
 #define SMBDIRECT_CHECK_STATUS_DISCONNECT(__sc, __expected_status) \
        __SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, \
                __SMBDIRECT_SOCKET_DISCONNECT(__sc);)