iscsi: fix manamgement task oops
PATCH 2/5 iscsi: fix manamgement task oops
from [email protected] and [email protected]
Fix bugs when forcing a mgmt task to fail and allow session recovery to cleanup the session/connection of any running mgmt tasks. When called during the in login state.
Signed-off-by Mike Christie <[email protected]>
drivers/scsi/libiscsi.c +21 -6
@@ -1538,10 +1538,11 @@ flush_control_queues(struct iscsi_sessio/* handle running */ list_for_each_entry_safe (mtask, tmp, &conn->mgmt_run_list, running) {debug_scsi ("flushing running mgmt task itt 0x%x\n" , mtask->itt); +list_del (&mtask->running); +if (mtask == conn->login_mtask)continue ; -list_del (&mtask->running); -__kfifo_put (session->mgmtpool.queue, (void *)&conn->mtask, +__kfifo_put (session->mgmtpool.queue, (void *)&mtask,sizeof (void *)); }
@@ -1573,12 +1574,22 @@ static void fail_all_commands(struct iscvoid iscsi_start_session_recovery (struct iscsi_session *session,struct iscsi_conn *conn,int flag) { +int old_stop_stage; +spin_lock_bh (&session->lock); -if (conn->stop_stage ==STOP_CONN_RECOVER || - conn->stop_stage ==STOP_CONN_TERM ) { +if (conn->stop_stage ==STOP_CONN_TERM ) {spin_unlock_bh (&session->lock);return ; } + +/* +* When this is called for the in_login state, we only want to clean +* up the login task and connection. +*/ +if (conn->stop_stage !=STOP_CONN_RECOVER ) + session->conn_cnt--; + + old_stop_stage = conn->stop_stage; conn->stop_stage = flag;spin_unlock_bh (&session->lock);
@@ -1590,7 +1601,6 @@ void iscsi_start_session_recovery(struct conn->c_stage =ISCSI_CONN_STOPPED ;set_bit (ISCSI_SUSPEND_BIT , &conn->suspend_tx); - session->conn_cnt--;if (session->conn_cnt ==0 || session->leadconn == conn) session->state =ISCSI_STATE_FAILED ;
@@ -1615,7 +1625,12 @@ void iscsi_start_session_recovery(struct conn->hdrdgst_en =0 ; conn->datadgst_en =0 ; -if (session->state ==ISCSI_STATE_FAILED ) +/* +* if this is called from the eh and and from userspace +* then we only need to block once. +*/ +if (session->state ==ISCSI_STATE_FAILED && + old_stop_stage !=STOP_CONN_RECOVER )iscsi_block_session (session_to_cls (session)); }mutex_unlock (&conn->xmitmutex);