static int iser_connect_error(struct rdma_cm_id *cma_id) { struct iser_conn *ib_conn; ib_conn = (struct iser_conn *)cma_id->context; ib_conn->state = ISER_CONN_DOWN; wake_up_interruptible(&ib_conn->wait); return iser_conn_put(ib_conn, 0); /* deref ib conn's cma id */ }
static void iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_iser_conn *iser_conn = conn->dd_data; struct iser_conn *ib_conn = iser_conn->ib_conn; iscsi_conn_teardown(cls_conn); if (ib_conn) { ib_conn->iser_conn = NULL; iser_conn_put(ib_conn); } }
static void iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_iser_conn *iser_conn = conn->dd_data; struct iser_conn *ib_conn = iser_conn->ib_conn; if (ib_conn) { iscsi_conn_stop(cls_conn, flag); iser_conn_put(ib_conn); } iser_conn->ib_conn = NULL; }
void iser_conn_terminate(struct iser_conn *ib_conn) { int err = 0; 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_put(ib_conn, 1); }
static void iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iser_conn *ib_conn = conn->dd_data; iscsi_conn_teardown(cls_conn); /* * Userspace will normally call the stop callback and * already have freed the ib_conn, but if it goofed up then * we free it here. */ if (ib_conn) { ib_conn->iscsi_conn = NULL; iser_conn_put(ib_conn, 1); /* deref iscsi/ib conn unbinding */ } }
/** * 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_put(ib_conn, 1); /* deref ib conn deallocate */ }
static void iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { struct iscsi_conn *conn = cls_conn->dd_data; struct iser_conn *ib_conn = conn->dd_data; /* * Userspace may have goofed up and not bound the connection or * might have only partially setup the connection. */ if (ib_conn) { iscsi_conn_stop(cls_conn, flag); /* * There is no unbind event so the stop callback * must release the ref from the bind. */ iser_conn_put(ib_conn, 1); /* deref iscsi/ib conn unbinding */ } conn->dd_data = NULL; }
static int iser_disconnected_handler(struct rdma_cm_id *cma_id) { struct iser_conn *ib_conn; int ret; ib_conn = (struct iser_conn *)cma_id->context; if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING)) iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, ISCSI_ERR_CONN_FAILED); if (ib_conn->post_recv_buf_count == 0 && (atomic_read(&ib_conn->post_send_buf_count) == 0)) { ib_conn->state = ISER_CONN_DOWN; wake_up_interruptible(&ib_conn->wait); } ret = iser_conn_put(ib_conn, 0); return ret; }
static int iser_disconnected_handler(struct rdma_cm_id *cma_id) { struct iser_conn *ib_conn; int ret; ib_conn = (struct iser_conn *)cma_id->context; /* getting here when the state is UP means that the conn is being * * terminated asynchronously from the iSCSI layer's perspective. */ if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING)) iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, ISCSI_ERR_CONN_FAILED); /* Complete the termination process if no posts are pending */ if (ib_conn->post_recv_buf_count == 0 && (atomic_read(&ib_conn->post_send_buf_count) == 0)) { ib_conn->state = ISER_CONN_DOWN; wake_up_interruptible(&ib_conn->wait); } ret = iser_conn_put(ib_conn, 0); /* deref ib conn's cma id */ return ret; }
/** * starts the process of connecting to the target * sleeps until 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, IB_QPT_RC); 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; iser_conn_put(ib_conn, 1); /* deref ib conn's cma id */ connect_failure: iser_conn_put(ib_conn, 1); /* deref ib conn deallocate */ return err; }