/** * starts the process of connecting to the target * sleeps untill the connection is established or rejected */ int iser_connect(struct iser_conn *ib_conn, struct sockaddr_in *src_addr, struct sockaddr_in *dst_addr, int non_blocking) { struct sockaddr *src, *dst; int err = 0; sprintf(ib_conn->name, "%pI4:%d", &dst_addr->sin_addr.s_addr, dst_addr->sin_port); /* the device is known only --after-- address resolution */ ib_conn->device = NULL; iser_err("connecting to: %pI4, port 0x%x\n", &dst_addr->sin_addr, dst_addr->sin_port); ib_conn->state = ISER_CONN_PENDING; iser_conn_get(ib_conn); /* ref ib conn's cma id */ ib_conn->cma_id = rdma_create_id(iser_cma_handler, (void *)ib_conn, RDMA_PS_TCP); if (IS_ERR(ib_conn->cma_id)) { err = PTR_ERR(ib_conn->cma_id); iser_err("rdma_create_id failed: %d\n", err); goto id_failure; } src = (struct sockaddr *)src_addr; dst = (struct sockaddr *)dst_addr; err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000); if (err) { iser_err("rdma_resolve_addr failed: %d\n", err); goto addr_failure; } if (!non_blocking) { wait_event_interruptible(ib_conn->wait, (ib_conn->state != ISER_CONN_PENDING)); if (ib_conn->state != ISER_CONN_UP) { err = -EIO; goto connect_failure; } } mutex_lock(&ig.connlist_mutex); list_add(&ib_conn->conn_list, &ig.connlist); mutex_unlock(&ig.connlist_mutex); return 0; id_failure: ib_conn->cma_id = NULL; addr_failure: ib_conn->state = ISER_CONN_DOWN; connect_failure: iser_conn_release(ib_conn, 1); return err; }
int iser_conn_put(struct iser_conn *ib_conn, int can_destroy_id) { if (atomic_dec_and_test(&ib_conn->refcount)) { iser_conn_release(ib_conn, can_destroy_id); return 1; } return 0; }
/** * triggers start of the disconnect procedures and wait for them to be done */ void iser_conn_terminate(struct iser_conn *ib_conn) { int err = 0; /* change the ib conn state only if the conn is UP, however always call * rdma_disconnect since this is the only way to cause the CMA to change * the QP state to ERROR */ iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING); err = rdma_disconnect(ib_conn->cma_id); if (err) iser_err("Failed to disconnect, conn: 0x%p err %d\n", ib_conn,err); wait_event_interruptible(ib_conn->wait, ib_conn->state == ISER_CONN_DOWN); iser_conn_release(ib_conn); }
void iser_conn_put(struct iser_conn *ib_conn) { if (atomic_dec_and_test(&ib_conn->refcount)) iser_conn_release(ib_conn); }