diff --git a/lib/iscsi/conn.c b/lib/iscsi/conn.c index 103b5f96f2..0e90978406 100644 --- a/lib/iscsi/conn.c +++ b/lib/iscsi/conn.c @@ -170,6 +170,24 @@ int spdk_initialize_iscsi_conns(void) return 0; } +static void +spdk_iscsi_poll_group_add_conn(struct spdk_iscsi_conn *conn, + spdk_iscsi_conn_fn fn) +{ + struct spdk_iscsi_poll_group *poll_group = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()]; + + conn->fn = fn; + STAILQ_INSERT_TAIL(&poll_group->connections, conn, link); +} + +static void +spdk_iscsi_poll_group_remove_conn(struct spdk_iscsi_conn *conn) +{ + struct spdk_iscsi_poll_group *poll_group = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()]; + + STAILQ_REMOVE(&poll_group->connections, conn, spdk_iscsi_conn, link); +} + /** * \brief Create an iSCSI connection from the given parameters and schedule it * on a reactor. @@ -285,8 +303,8 @@ error_return: conn->lcore = spdk_env_get_current_core(); __sync_fetch_and_add(&g_num_connections[conn->lcore], 1); - conn->poller = spdk_poller_register(spdk_iscsi_conn_login_do_work, conn, 0); + spdk_iscsi_poll_group_add_conn(conn, spdk_iscsi_conn_login_do_work); return 0; } @@ -563,8 +581,9 @@ spdk_iscsi_conn_stop_poller(struct spdk_iscsi_conn *conn) assert(conn->dev != NULL); spdk_scsi_dev_free_io_channels(conn->dev); } + __sync_fetch_and_sub(&g_num_connections[spdk_env_get_current_core()], 1); - spdk_poller_unregister(&conn->poller); + spdk_iscsi_poll_group_remove_conn(conn); } void spdk_shutdown_iscsi_conns(void) @@ -1144,8 +1163,7 @@ spdk_iscsi_conn_full_feature_migrate(void *arg1, void *arg2) /* The poller has been unregistered, so now we can re-register it on the new core. */ conn->lcore = spdk_env_get_current_core(); - conn->poller = spdk_poller_register(spdk_iscsi_conn_full_feature_do_work, conn, - 0); + spdk_iscsi_poll_group_add_conn(conn, spdk_iscsi_conn_full_feature_do_work); } void @@ -1195,7 +1213,8 @@ spdk_iscsi_conn_login_do_work(void *arg) spdk_iscsi_conn_stop_poller(conn); __sync_fetch_and_add(&g_num_connections[lcore], 1); - event = spdk_event_allocate(lcore, spdk_iscsi_conn_full_feature_migrate, conn, NULL); + event = spdk_event_allocate(lcore, spdk_iscsi_conn_full_feature_migrate, + conn, NULL); spdk_event_call(event); } } diff --git a/lib/iscsi/conn.h b/lib/iscsi/conn.h index 93de74395f..2168ee7f17 100644 --- a/lib/iscsi/conn.h +++ b/lib/iscsi/conn.h @@ -67,6 +67,7 @@ #define TRACE_ISCSI_CONN_IDLE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x7) struct spdk_poller; +typedef void (*spdk_iscsi_conn_fn)(void *arg); struct spdk_iscsi_conn { int id; @@ -159,7 +160,7 @@ struct spdk_iscsi_conn { char *partial_text_parameter; STAILQ_ENTRY(spdk_iscsi_conn) link; - struct spdk_poller *poller; + spdk_iscsi_conn_fn fn; struct spdk_poller *flush_poller; TAILQ_HEAD(queued_r2t_tasks, spdk_iscsi_task) queued_r2t_tasks; TAILQ_HEAD(active_r2t_tasks, spdk_iscsi_task) active_r2t_tasks; diff --git a/lib/iscsi/iscsi.h b/lib/iscsi/iscsi.h index 866da14553..7059fdfc97 100644 --- a/lib/iscsi/iscsi.h +++ b/lib/iscsi/iscsi.h @@ -39,6 +39,8 @@ #include "spdk/bdev.h" #include "spdk/iscsi_spec.h" +#include "spdk/event.h" +#include "spdk/io_channel.h" #include "iscsi/param.h" #include "iscsi/tgt_node.h" @@ -254,6 +256,12 @@ struct spdk_iscsi_sess { uint32_t current_text_itt; }; +struct spdk_iscsi_poll_group { + uint32_t core; + struct spdk_poller *poller; + STAILQ_HEAD(connections, spdk_iscsi_conn) connections; +}; + struct spdk_iscsi_globals { char *authfile; char *nodebase; @@ -288,6 +296,7 @@ struct spdk_iscsi_globals { struct spdk_mempool *task_pool; struct spdk_iscsi_sess **session; + struct spdk_iscsi_poll_group *poll_group; }; #define ISCSI_SECURITY_NEGOTIATION_PHASE 0 diff --git a/lib/iscsi/iscsi_subsystem.c b/lib/iscsi/iscsi_subsystem.c index b775566ee2..fe1d280752 100644 --- a/lib/iscsi/iscsi_subsystem.c +++ b/lib/iscsi/iscsi_subsystem.c @@ -818,7 +818,6 @@ spdk_iscsi_app_read_parameters(void) return 0; } - static void spdk_iscsi_init_complete(int rc) { @@ -831,6 +830,52 @@ spdk_iscsi_init_complete(int rc) cb_fn(cb_arg, rc); } +static void +spdk_iscsi_poll_group_poll(void *ctx) +{ + struct spdk_iscsi_poll_group *group = ctx; + struct spdk_iscsi_conn *conn, *tmp; + + STAILQ_FOREACH_SAFE(conn, &group->connections, link, tmp) { + conn->fn(conn); + } +} + +static void +iscsi_create_poll_group_done(void *ctx) +{ + spdk_iscsi_init_complete(0); +} + +static void +iscsi_create_poll_group(void *ctx) +{ + struct spdk_iscsi_poll_group *pg; + + pg = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()]; + pg->core = spdk_env_get_current_core(); + assert(pg != NULL); + + STAILQ_INIT(&pg->connections); + pg->poller = spdk_poller_register(spdk_iscsi_poll_group_poll, pg, 0); +} + +static void +spdk_initialize_iscsi_poll_group(void) +{ + size_t g_num_poll_groups = spdk_env_get_last_core() + 1; + + g_spdk_iscsi.poll_group = calloc(g_num_poll_groups, sizeof(struct spdk_iscsi_poll_group)); + if (!g_spdk_iscsi.poll_group) { + SPDK_ERRLOG("Failed to allocated iscsi poll group\n"); + spdk_iscsi_init_complete(-1); + return; + } + + /* Send a message to each thread and create a poll group */ + spdk_for_each_thread(iscsi_create_poll_group, NULL, iscsi_create_poll_group_done); +} + void spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg) { @@ -868,7 +913,7 @@ spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg) return; } - spdk_iscsi_init_complete(0); + spdk_initialize_iscsi_poll_group(); } void @@ -892,6 +937,7 @@ spdk_iscsi_fini_done(void) spdk_iscsi_portal_grp_array_destroy(); free(g_spdk_iscsi.authfile); free(g_spdk_iscsi.nodebase); + free(g_spdk_iscsi.poll_group); pthread_mutex_destroy(&g_spdk_iscsi.mutex); g_fini_cb_fn(g_fini_cb_arg);