#define log_rdma_mr(level, fmt, args...) \
log_rdma(level, LOG_RDMA_MR, fmt, ##args)
+static void smbd_disconnect_wake_up_all(struct smbdirect_socket *sc)
+{
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ */
+ wake_up_all(&sc->status_wait);
+ wake_up_all(&sc->send_io.credits.wait_queue);
+ wake_up_all(&sc->send_io.pending.dec_wait_queue);
+ wake_up_all(&sc->send_io.pending.zero_wait_queue);
+ wake_up_all(&sc->recv_io.reassembly.wait_queue);
+ wake_up_all(&sc->mr_io.ready.wait_queue);
+ wake_up_all(&sc->mr_io.cleanup.wait_queue);
+}
+
static void smbd_disconnect_rdma_work(struct work_struct *work)
{
struct smbdirect_socket *sc =
case SMBDIRECT_SOCKET_DESTROYED:
break;
}
+
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ */
+ smbd_disconnect_wake_up_all(sc);
}
static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
break;
}
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ */
+ smbd_disconnect_wake_up_all(sc);
+
queue_work(sc->workqueue, &sc->disconnect_work);
}
log_rdma_event(ERR, "connecting failed event=%s\n", event_name);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING);
sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED;
- wake_up_all(&sc->status_wait);
+ smbd_disconnect_rdma_work(&sc->disconnect_work);
break;
case RDMA_CM_EVENT_ROUTE_ERROR:
log_rdma_event(ERR, "connecting failed event=%s\n", event_name);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING);
sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED;
- wake_up_all(&sc->status_wait);
+ smbd_disconnect_rdma_work(&sc->disconnect_work);
break;
case RDMA_CM_EVENT_ESTABLISHED:
log_rdma_event(ERR, "connecting failed event=%s\n", event_name);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED;
- wake_up_all(&sc->status_wait);
+ smbd_disconnect_rdma_work(&sc->disconnect_work);
break;
case RDMA_CM_EVENT_DEVICE_REMOVAL:
/* This happens when we fail the negotiation */
if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_FAILED) {
log_rdma_event(ERR, "event=%s during negotiation\n", event_name);
- sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
- smbd_disconnect_rdma_work(&sc->disconnect_work);
- wake_up_all(&sc->status_wait);
- break;
}
sc->status = SMBDIRECT_SOCKET_DISCONNECTED;
smbd_disconnect_rdma_work(&sc->disconnect_work);
- wake_up_all(&sc->status_wait);
- wake_up_all(&sc->recv_io.reassembly.wait_queue);
- wake_up_all(&sc->send_io.credits.wait_queue);
break;
default:
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING);
if (!negotiate_done) {
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
- wake_up_all(&sc->status_wait);
+ smbd_disconnect_rdma_connection(sc);
} else {
sc->status = SMBDIRECT_SOCKET_CONNECTED;
wake_up(&sc->status_wait);
sc->status == SMBDIRECT_SOCKET_DISCONNECTED);
}
+ /*
+ * Wake up all waiters in all wait queues
+ * in order to notice the broken connection.
+ *
+ * Most likely this was already called via
+ * smbd_disconnect_rdma_work(), but call it again...
+ */
+ smbd_disconnect_wake_up_all(sc);
+
log_rdma_event(INFO, "cancelling recv_io.posted.refill_work\n");
disable_work_sync(&sc->recv_io.posted.refill_work);
* path when sending data, and then release memory registrations.
*/
log_rdma_event(INFO, "freeing mr list\n");
- wake_up_all(&sc->mr_io.ready.wait_queue);
while (atomic_read(&sc->mr_io.used.count)) {
cifs_server_unlock(server);
msleep(1000);