The race condition can be observed with the following sequence of events:
- For every active sessions, issue an ISCSI_ERR_CONN_FAILED nl msg
(This will eventually put all active connections into the actor_list ready
to execute the session_conn_reopen procedure)
- Asynchronously after a few seconds, call the iscsi_host_remove procedure
(This will notify iscsid with the ISCSI_ERR_INVALID_HOST nl message)

The current code actually handles this by advancing the INVALID_HOST
session_conn_error actor scheduing to the head via the actor_schedule_head
procedure.  However, if the current actor thread was call-backed from the
actor_poll loop, then this head scheduling will actually put the INVALID_HOST
actor onto the poll_list instead of the actor_list.

If there are subsequent elements in the actor_list which triggers the reopen
path, then the conn_context for the INVALID_HOST for that particular
connection will get flushed (+ actor_delete).  This will then lockup the
libiscsi's iscsi_host_remove call as it will wait indefinitely on all
sessions to be removed.

The fix is to put this head scheduling to the head of the actor_list
regardless of poll mode or not.  This will allow all INVALID_PATH actors
to have a chance to get executed before any subsequent reopen actors.

Signed-off-by: Eddie Wai <eddie....@broadcom.com>
---
 usr/actor.c |   13 ++++++-------
 1 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/usr/actor.c b/usr/actor.c
index e88d197..45f3a51 100644
--- a/usr/actor.c
+++ b/usr/actor.c
@@ -112,14 +112,13 @@ actor_schedule_private(actor_t *thread, uint32_t 
ttschedule, int head)
                 * state to scheduled, else add current time to ttschedule and
                 * insert in the queue at the correct point */
                if (delay_time == 0) {
-                       if (poll_in_progress) {
+                       /* For head addition, it must go onto the head of the
+                          actor_list regardless if poll is in progress or not
+                        */
+                       if (poll_in_progress && !head) {
                                thread->state = ACTOR_POLL_WAITING;
-                               if (head)
-                                       list_add(&thread->list,
-                                                &poll_list);
-                               else
-                                       list_add_tail(&thread->list,
-                                                     &poll_list);
+                               list_add_tail(&thread->list,
+                                             &poll_list);
                        } else {
                                thread->state = ACTOR_SCHEDULED;
                                if (head)
-- 
1.7.0.5


-- 
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-is...@googlegroups.com.
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/open-iscsi?hl=en.

Reply via email to