smb: smbdirect: introduce smbdirect_socket_schedule_cleanup[{_lvl,_status}]()

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>
This commit is contained in:
Stefan Metzmacher 2025-08-26 17:25:24 +02:00 committed by Steve French
parent 1be83fad0c
commit d856148601
3 changed files with 122 additions and 0 deletions

View File

@ -10,4 +10,26 @@
#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__ */

View 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 =

View 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);)