diff --git a/usr/actor.c b/usr/actor.c index b487632..00f5c58 100644 --- a/usr/actor.c +++ b/usr/actor.c @@ -90,7 +90,7 @@ actor_delete(actor_t *thread) } static void -actor_schedule_private(actor_t *thread, uint32_t ttschedule) +actor_schedule_private(actor_t *thread, uint32_t ttschedule, int head) { uint64_t delay_time, current_time; actor_t *next_thread; @@ -115,10 +115,20 @@ actor_schedule_private(actor_t *thread, uint32_t ttschedule) if (delay_time == 0) { if (poll_in_progress) { thread->state = ACTOR_POLL_WAITING; - list_add_tail(&thread->list, &poll_list); + if (head) + list_add(&thread->list, + &poll_list); + else + list_add_tail(&thread->list, + &poll_list); } else { thread->state = ACTOR_SCHEDULED; - list_add_tail(&thread->list, &actor_list); + if (head) + list_add(&thread->list, + &actor_list); + else + list_add_tail(&thread->list, + &actor_list); } } else { thread->state = ACTOR_WAITING; @@ -159,9 +169,15 @@ done: } void +actor_schedule_head(actor_t *thread) +{ + actor_schedule_private(thread, 0, 1); +} + +void actor_schedule(actor_t *thread) { - actor_schedule_private(thread, 0); + actor_schedule_private(thread, 0, 0); } void @@ -169,7 +185,7 @@ actor_timer(actor_t *thread, uint32_t timeout, void (*callback)(void *), void *data) { actor_new(thread, callback, data); - actor_schedule_private(thread, timeout); + actor_schedule_private(thread, timeout, 0); } int @@ -178,7 +194,7 @@ actor_timer_mod(actor_t *thread, uint32_t timeout, void *data) if (thread->state == ACTOR_WAITING) { list_del_init(&thread->list); thread->data = data; - actor_schedule_private(thread, timeout); + actor_schedule_private(thread, timeout, 0); return 1; } return 0; diff --git a/usr/actor.h b/usr/actor.h index 7a71d42..704224d 100644 --- a/usr/actor.h +++ b/usr/actor.h @@ -44,6 +44,7 @@ typedef struct actor { extern void actor_new(actor_t *thread, void (*callback)(void *), void * data); extern void actor_delete(actor_t *thread); +extern void actor_schedule_head(actor_t *thread); extern void actor_schedule(actor_t *thread); extern void actor_timer(actor_t *thread, uint32_t timeout, void (*callback)(void *), void *data); diff --git a/usr/initiator.c b/usr/initiator.c index d7ff50f..dc0deca 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -1981,6 +1981,8 @@ void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, struct iscsi_conn *conn, unsigned long tmo, int event) { + enum iscsi_err error; + log_debug(7, "sched conn context %p event %d, tmo %lu", &conn_context->actor, event, tmo); @@ -1992,9 +1994,19 @@ void iscsi_sched_conn_context(struct iscsi_conn_context *conn_context, actor_schedule(&conn_context->actor); break; case EV_CONN_ERROR: + error = *(enum iscsi_err *)conn_context->data; + actor_new(&conn_context->actor, session_conn_error, conn_context); - actor_schedule(&conn_context->actor); + /* + * We handle invalid host, by killing the session. + * It must go at the head of the queue, so we do not + * initiate error handling or logout or some other op. + */ + if (error == ISCSI_ERR_INVALID_HOST) + actor_schedule_head(&conn_context->actor); + else + actor_schedule(&conn_context->actor); break; case EV_CONN_POLL: actor_new(&conn_context->actor, session_conn_poll,