void rds_hb_worker(struct work_struct *work) { struct rds_connection *conn = container_of(work, struct rds_connection, c_hb_w.work); unsigned long now = get_seconds(); int ret; if (!rds_conn_hb_timeout || conn->c_loopback) return; if (rds_conn_state(conn) == RDS_CONN_UP) { if (!conn->c_hb_start) { ret = rds_send_hb(conn, 0); if (ret) { rdsdebug("RDS/IB: rds_hb_worker: failed %d\n", ret); return; } conn->c_hb_start = now; } else if (now - conn->c_hb_start > rds_conn_hb_timeout) { printk(KERN_NOTICE "RDS/IB: connection <%u.%u.%u.%u,%u.%u.%u.%u,%d> " "timed out (0x%lx,0x%lx)..disconnecting and reconnecting\n", NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr), conn->c_tos, conn->c_hb_start, now); rds_conn_drop(conn); return; } queue_delayed_work(rds_wq, &conn->c_hb_w, HZ); } }
static int rds_tcp_accept_one(struct socket *sock) { struct socket *new_sock = NULL; struct rds_connection *conn; int ret; struct inet_sock *inet; ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type, sock->sk->sk_protocol, &new_sock); if (ret) goto out; new_sock->type = sock->type; new_sock->ops = sock->ops; ret = sock->ops->accept(sock, new_sock, O_NONBLOCK); if (ret < 0) goto out; rds_tcp_tune(new_sock); inet = inet_sk(new_sock->sk); rdsdebug("accepted tcp %pI4:%u -> %pI4:%u\n", &inet->inet_saddr, ntohs(inet->inet_sport), &inet->inet_daddr, ntohs(inet->inet_dport)); conn = rds_conn_create(inet->inet_saddr, inet->inet_daddr, &rds_tcp_transport, GFP_KERNEL); if (IS_ERR(conn)) { ret = PTR_ERR(conn); goto out; } /* * see the comment above rds_queue_delayed_reconnect() */ if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING)) { if (rds_conn_state(conn) == RDS_CONN_UP) rds_tcp_stats_inc(s_tcp_listen_closed_stale); else rds_tcp_stats_inc(s_tcp_connect_raced); rds_conn_drop(conn); ret = 0; goto out; } rds_tcp_set_callbacks(new_sock, conn); rds_connect_complete(conn); new_sock = NULL; ret = 0; out: if (new_sock) sock_release(new_sock); return ret; }
void rds_recv_worker(struct work_struct *work) { struct rds_connection *conn = container_of(work, struct rds_connection, c_recv_w.work); int ret; if (rds_conn_state(conn) == RDS_CONN_UP) { ret = conn->c_trans->recv(conn); rdsdebug("conn %p ret %d\n", conn, ret); switch (ret) { case -EAGAIN: rds_stats_inc(s_recv_immediate_retry); queue_delayed_work(rds_wq, &conn->c_recv_w, 0); break; case -ENOMEM: rds_stats_inc(s_recv_delayed_retry); queue_delayed_work(rds_wq, &conn->c_recv_w, 2); default: break; } } }
void rds_send_worker(struct work_struct *work) { struct rds_connection *conn = container_of(work, struct rds_connection, c_send_w.work); int ret; if (rds_conn_state(conn) == RDS_CONN_UP) { clear_bit(RDS_LL_SEND_FULL, &conn->c_flags); ret = rds_send_xmit(conn); cond_resched(); rdsdebug("conn %p ret %d\n", conn, ret); switch (ret) { case -EAGAIN: rds_stats_inc(s_send_immediate_retry); queue_delayed_work(rds_wq, &conn->c_send_w, 0); break; case -ENOMEM: rds_stats_inc(s_send_delayed_retry); queue_delayed_work(rds_wq, &conn->c_send_w, 2); default: break; } } }
int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, struct rdma_cm_event *event) { /* this can be null in the listening path */ struct rds_connection *conn = cm_id->context; struct rds_transport *trans; int ret = 0; rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id, event->event, rdma_event_msg(event->event)); if (cm_id->device->node_type == RDMA_NODE_RNIC) trans = &rds_iw_transport; else trans = &rds_ib_transport; /* Prevent shutdown from tearing down the connection * while we're executing. */ if (conn) { mutex_lock(&conn->c_cm_lock); /* If the connection is being shut down, bail out * right away. We return 0 so cm_id doesn't get * destroyed prematurely */ if (rds_conn_state(conn) == RDS_CONN_DISCONNECTING) { /* Reject incoming connections while we're tearing * down an existing one. */ if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) ret = 1; goto out; } } switch (event->event) { case RDMA_CM_EVENT_CONNECT_REQUEST: ret = trans->cm_handle_connect(cm_id, event); break; case RDMA_CM_EVENT_ADDR_RESOLVED: /* XXX do we need to clean up if this fails? */ ret = rdma_resolve_route(cm_id, RDS_RDMA_RESOLVE_TIMEOUT_MS); break; case RDMA_CM_EVENT_ROUTE_RESOLVED: /* Connection could have been dropped so make sure the * cm_id is valid before proceeding */ if (conn) { struct rds_ib_connection *ibic; ibic = conn->c_transport_data; if (ibic && ibic->i_cm_id == cm_id) ret = trans->cm_initiate_connect(cm_id); else rds_conn_drop(conn); } break; case RDMA_CM_EVENT_ESTABLISHED: trans->cm_connect_complete(conn, event); break; case RDMA_CM_EVENT_ADDR_ERROR: case RDMA_CM_EVENT_ROUTE_ERROR: case RDMA_CM_EVENT_CONNECT_ERROR: case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_REJECTED: case RDMA_CM_EVENT_DEVICE_REMOVAL: case RDMA_CM_EVENT_ADDR_CHANGE: if (conn) rds_conn_drop(conn); break; case RDMA_CM_EVENT_DISCONNECTED: rdsdebug("DISCONNECT event - dropping connection " "%pI4->%pI4\n", &conn->c_laddr, &conn->c_faddr); rds_conn_drop(conn); break; default: /* things like device disconnect? */ printk(KERN_ERR "RDS: unknown event %u (%s)!\n", event->event, rdma_event_msg(event->event)); break; } out: if (conn) mutex_unlock(&conn->c_cm_lock); rdsdebug("id %p event %u (%s) handling ret %d\n", cm_id, event->event, rdma_event_msg(event->event), ret); return ret; }
int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, struct rdma_cm_event *event) { /* this can be null in the listening path */ struct rds_connection *conn = cm_id->context; struct rds_transport *trans; int ret = 0; rdsdebug("conn %p id %p handling event %u\n", conn, cm_id, event->event); if (cm_id->device->node_type == RDMA_NODE_RNIC) trans = &rds_iw_transport; else trans = &rds_ib_transport; /* Prevent shutdown from tearing down the connection * while we're executing. */ if (conn) { mutex_lock(&conn->c_cm_lock); /* If the connection is being shut down, bail out * right away. We return 0 so cm_id doesn't get * destroyed prematurely */ if (rds_conn_state(conn) == RDS_CONN_DISCONNECTING) { /* Reject incoming connections while we're tearing * down an existing one. */ if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST) ret = 1; goto out; } } switch (event->event) { case RDMA_CM_EVENT_CONNECT_REQUEST: ret = trans->cm_handle_connect(cm_id, event); break; case RDMA_CM_EVENT_ADDR_RESOLVED: /* XXX do we need to clean up if this fails? */ ret = rdma_resolve_route(cm_id, RDS_RDMA_RESOLVE_TIMEOUT_MS); break; case RDMA_CM_EVENT_ROUTE_RESOLVED: /* XXX worry about racing with listen acceptance */ ret = trans->cm_initiate_connect(cm_id); break; case RDMA_CM_EVENT_ESTABLISHED: trans->cm_connect_complete(conn, event); break; case RDMA_CM_EVENT_ADDR_ERROR: case RDMA_CM_EVENT_ROUTE_ERROR: case RDMA_CM_EVENT_CONNECT_ERROR: case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_REJECTED: case RDMA_CM_EVENT_DEVICE_REMOVAL: case RDMA_CM_EVENT_ADDR_CHANGE: if (conn) rds_conn_drop(conn); break; case RDMA_CM_EVENT_DISCONNECTED: printk(KERN_WARNING "RDS/RDMA: DISCONNECT event - dropping connection " "%u.%u.%u.%u->%u.%u.%u.%u\n", NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr)); rds_conn_drop(conn); break; default: /* things like device disconnect? */ printk(KERN_ERR "unknown event %u\n", event->event); BUG(); break; } out: if (conn) { //struct rds_iw_connection *ic = conn->c_transport_data; /* If we return non-zero, we must to hang on to the cm_id */ //BUG_ON(ic->i_cm_id == cm_id && ret); mutex_unlock(&conn->c_cm_lock); } rdsdebug("id %p event %u handling ret %d\n", cm_id, event->event, ret); return ret; }