diff --git a/lib/connect.c b/lib/connect.c index a17b4e5..ff28e23 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -418,6 +418,14 @@ int iscsi_reconnect(struct iscsi_context *iscsi) return -1; } + /* default transport is initialized as TCP in iscsi_create_context, + we have to overwrite transport in new iscsi as old iscsi. + */ + if (iscsi_init_transport(tmp_iscsi, iscsi->transport)) { + ISCSI_LOG(iscsi, 2, "failed to initializing transport for reconnection"); + return -1; + } + ISCSI_LOG(iscsi, 2, "reconnect initiated"); iscsi_set_targetname(tmp_iscsi, iscsi->target_name); diff --git a/lib/init.c b/lib/init.c index 13098f0..a120e88 100644 --- a/lib/init.c +++ b/lib/init.c @@ -218,7 +218,7 @@ iscsi_create_context(const char *initiator_name) /* initalize transport of context */ if (iscsi_init_transport(iscsi, TCP_TRANSPORT)) { - iscsi_set_error(iscsi, "Failed allocating transport"); + free(iscsi); return NULL; } @@ -393,9 +393,7 @@ iscsi_destroy_context(struct iscsi_context *iscsi) return 0; } - if (iscsi->fd != -1) { - iscsi_disconnect(iscsi); - } + iscsi_disconnect(iscsi); iscsi_cancel_pdus(iscsi); diff --git a/lib/iser.c b/lib/iser.c index 66f51a7..81f3687 100644 --- a/lib/iser.c +++ b/lib/iser.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include "slist.h" @@ -48,6 +49,9 @@ #ifdef __linux +/* the name can be up to 16 bytes long, including the terminating null byte*/ +#define ISER_CM_THREAD_NAME "iscsi_cm_thread" + /* MUST keep in sync with socket.c */ union socket_address { struct sockaddr_in sin; @@ -194,6 +198,7 @@ iser_free_iser_conn_res(struct iser_conn *iser_conn, bool destroy) if (iser_conn->cmthread) { pthread_cancel(iser_conn->cmthread); + pthread_join(iser_conn->cmthread, NULL); iser_conn->cmthread = 0; } @@ -289,8 +294,10 @@ iscsi_iser_disconnect(struct iscsi_context *iscsi) { struct iser_conn *iser_conn = iscsi->opaque; - iser_conn_terminate(iser_conn); - iser_conn_release(iser_conn); + if (iser_conn) { + iser_conn_terminate(iser_conn); + iser_conn_release(iser_conn); + } iscsi->fd = -1; iscsi->is_connected = 0; @@ -1032,7 +1039,7 @@ iser_reg_mr(struct iser_conn *iser_conn) for (i = 0 ; i < NUM_MRS ; i++) { - tx_desc = iscsi_malloc(iscsi, sizeof(*tx_desc)); + tx_desc = iscsi_zmalloc(iscsi, sizeof(*tx_desc)); if (tx_desc == NULL) { iscsi_set_error(iscsi, "Out-Of-Memory, failed to allocate data buffer"); return -1; @@ -1370,6 +1377,9 @@ static void *cm_thread(void *arg) int ret; struct iscsi_context *iscsi = iser_conn->cma_id->context; + /* supported since Linux 2.6.9, not fatal error, ignore return value */ + prctl(PR_SET_NAME, ISER_CM_THREAD_NAME); + while (1) { ret = rdma_get_cm_event(iser_conn->cma_channel, &iser_conn->cma_event); if (ret) { @@ -1454,6 +1464,25 @@ iscsi_iser_connect(struct iscsi_context *iscsi, union socket_address *sa,__attri iscsi->socket_status_cb(iscsi, SCSI_STATUS_GOOD, NULL, iscsi->connect_data); iscsi->socket_status_cb = NULL; + if (iscsi->old_iscsi && iscsi->opaque != iscsi->old_iscsi->opaque) { + struct iser_conn *old_iser_conn = iscsi->old_iscsi->opaque; + int oldfd = old_iser_conn->comp_channel->fd; + int newfd = iser_conn->comp_channel->fd; + + iser_conn_terminate(old_iser_conn); + iser_conn_release(old_iser_conn); + + if (dup2(newfd, oldfd) == -1) { + return -1; + } + + close(newfd); + iser_conn->comp_channel->fd = oldfd; + + iscsi_free(iscsi->old_iscsi, iscsi->old_iscsi->opaque); + iscsi->old_iscsi->opaque = NULL; + } + return 0; } @@ -1471,7 +1500,7 @@ static iscsi_transport iscsi_transport_iser = { void iscsi_init_iser_transport(struct iscsi_context *iscsi) { iscsi->drv = &iscsi_transport_iser; - iscsi->opaque = iscsi_malloc(iscsi, sizeof(struct iser_conn)); + iscsi->opaque = iscsi_zmalloc(iscsi, sizeof(struct iser_conn)); iscsi->transport = ISER_TRANSPORT; /* Update iSCSI params as per iSER transport */ iscsi->initiator_max_recv_data_segment_length = ISCSI_DEF_MAX_RECV_SEG_LEN; diff --git a/lib/socket.c b/lib/socket.c index 79471a3..cd6c97a 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -425,6 +425,9 @@ iscsi_tcp_disconnect(struct iscsi_context *iscsi) int iscsi_disconnect(struct iscsi_context *iscsi) { + if (!iscsi || !iscsi->drv || !iscsi->drv->disconnect) + return -1; + return iscsi->drv->disconnect(iscsi); }