fs/smb/smbdirect/connection.c

Source file repositories/reference/linux-study-clean/fs/smb/smbdirect/connection.c

File Facts

System
Linux kernel
Corpus path
fs/smb/smbdirect/connection.c
Extension
.c
Size
62197 bytes
Lines
2182
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct smbdirect_map_sges {
	struct ib_sge *sge;
	size_t num_sge;
	size_t max_sge;
	struct ib_device *device;
	u32 local_dma_lkey;
	enum dma_data_direction direction;
};

static ssize_t smbdirect_map_sges_from_iter(struct iov_iter *iter, size_t len,
					    struct smbdirect_map_sges *state);

static void smbdirect_connection_recv_io_refill_work(struct work_struct *work);
static void smbdirect_connection_send_immediate_work(struct work_struct *work);

static void smbdirect_connection_qp_event_handler(struct ib_event *event, void *context)
{
	struct smbdirect_socket *sc = context;

	smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
		"%s on device %.*s socket %p (cm_id=%p) status %s first_error %1pe\n",
		ib_event_msg(event->event),
		IB_DEVICE_NAME_MAX,
		event->device->name,
		sc, sc->rdma.cm_id,
		smbdirect_socket_status_string(sc->status),
		SMBDIRECT_DEBUG_ERR_PTR(sc->first_error));

	switch (event->event) {
	case IB_EVENT_CQ_ERR:
	case IB_EVENT_QP_FATAL:
		smbdirect_socket_schedule_cleanup(sc, -ECONNABORTED);
		break;

	default:
		break;
	}
}

static int smbdirect_connection_rdma_event_handler(struct rdma_cm_id *id,
						   struct rdma_cm_event *event)
{
	struct smbdirect_socket *sc = id->context;
	int ret = -ECONNRESET;

	if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
		ret = -ENETDOWN;
	if (IS_ERR(SMBDIRECT_DEBUG_ERR_PTR(event->status)))
		ret = event->status;

	/*
	 * cma_cm_event_handler() has
	 * lockdep_assert_held(&id_priv->handler_mutex);
	 *
	 * Mutexes are not allowed in interrupts,
	 * and we rely on not being in an interrupt here.
	 */
	WARN_ON_ONCE(in_interrupt());

	if (event->event != sc->rdma.expected_event) {
		smbdirect_log_rdma_event(sc, SMBDIRECT_LOG_ERR,
			"%s (first_error=%1pe, expected=%s) => event=%s status=%d => ret=%1pe\n",
			smbdirect_socket_status_string(sc->status),
			SMBDIRECT_DEBUG_ERR_PTR(sc->first_error),
			rdma_event_msg(sc->rdma.expected_event),
			rdma_event_msg(event->event),
			event->status,
			SMBDIRECT_DEBUG_ERR_PTR(ret));

		/*
		 * If we get RDMA_CM_EVENT_DEVICE_REMOVAL,
		 * we should change to SMBDIRECT_SOCKET_DISCONNECTED,
		 * so that rdma_disconnect() is avoided later via
		 * smbdirect_socket_schedule_cleanup[_status]() =>
		 * smbdirect_socket_cleanup_work().
		 *
		 * As otherwise we'd set SMBDIRECT_SOCKET_DISCONNECTING,
		 * but never ever get RDMA_CM_EVENT_DISCONNECTED and
		 * never reach SMBDIRECT_SOCKET_DISCONNECTED.
		 */
		if (event->event == RDMA_CM_EVENT_DEVICE_REMOVAL)
			smbdirect_socket_schedule_cleanup_status(sc,
								 SMBDIRECT_LOG_ERR,
								 ret,
								 SMBDIRECT_SOCKET_DISCONNECTED);
		else
			smbdirect_socket_schedule_cleanup(sc, ret);
		if (sc->ib.qp)
			ib_drain_qp(sc->ib.qp);
		return 0;

Annotation

Implementation Notes