aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-05-02 20:46:40 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-05-10 11:12:04 -0400
commited2abc7ff19dc99c6242a70f8578a17b2ff0d0ce (patch)
tree3bf226387f002ee6c67619afd1a950e1d0bde30f /drivers/scsi
parent264faaaa12544e7914928ad57ccba21907cad56b (diff)
[SCSI] iscsi: fix manamgement task oops
from patmans@us.ibm.com and michaelc@cs.wisc.edu 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 <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/libiscsi.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 274a1374ab64..8c51f6c36661 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1538,10 +1538,11 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
1538 /* handle running */ 1538 /* handle running */
1539 list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { 1539 list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
1540 debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); 1540 debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
1541 list_del(&mtask->running);
1542
1541 if (mtask == conn->login_mtask) 1543 if (mtask == conn->login_mtask)
1542 continue; 1544 continue;
1543 list_del(&mtask->running); 1545 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
1544 __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
1545 sizeof(void*)); 1546 sizeof(void*));
1546 } 1547 }
1547 1548
@@ -1573,12 +1574,22 @@ static void fail_all_commands(struct iscsi_conn *conn)
1573void iscsi_start_session_recovery(struct iscsi_session *session, 1574void iscsi_start_session_recovery(struct iscsi_session *session,
1574 struct iscsi_conn *conn, int flag) 1575 struct iscsi_conn *conn, int flag)
1575{ 1576{
1577 int old_stop_stage;
1578
1576 spin_lock_bh(&session->lock); 1579 spin_lock_bh(&session->lock);
1577 if (conn->stop_stage == STOP_CONN_RECOVER || 1580 if (conn->stop_stage == STOP_CONN_TERM) {
1578 conn->stop_stage == STOP_CONN_TERM) {
1579 spin_unlock_bh(&session->lock); 1581 spin_unlock_bh(&session->lock);
1580 return; 1582 return;
1581 } 1583 }
1584
1585 /*
1586 * When this is called for the in_login state, we only want to clean
1587 * up the login task and connection.
1588 */
1589 if (conn->stop_stage != STOP_CONN_RECOVER)
1590 session->conn_cnt--;
1591
1592 old_stop_stage = conn->stop_stage;
1582 conn->stop_stage = flag; 1593 conn->stop_stage = flag;
1583 spin_unlock_bh(&session->lock); 1594 spin_unlock_bh(&session->lock);
1584 1595
@@ -1590,7 +1601,6 @@ void iscsi_start_session_recovery(struct iscsi_session *session,
1590 conn->c_stage = ISCSI_CONN_STOPPED; 1601 conn->c_stage = ISCSI_CONN_STOPPED;
1591 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); 1602 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1592 1603
1593 session->conn_cnt--;
1594 if (session->conn_cnt == 0 || session->leadconn == conn) 1604 if (session->conn_cnt == 0 || session->leadconn == conn)
1595 session->state = ISCSI_STATE_FAILED; 1605 session->state = ISCSI_STATE_FAILED;
1596 1606
@@ -1615,7 +1625,12 @@ void iscsi_start_session_recovery(struct iscsi_session *session,
1615 conn->hdrdgst_en = 0; 1625 conn->hdrdgst_en = 0;
1616 conn->datadgst_en = 0; 1626 conn->datadgst_en = 0;
1617 1627
1618 if (session->state == ISCSI_STATE_FAILED) 1628 /*
1629 * if this is called from the eh and and from userspace
1630 * then we only need to block once.
1631 */
1632 if (session->state == ISCSI_STATE_FAILED &&
1633 old_stop_stage != STOP_CONN_RECOVER)
1619 iscsi_block_session(session_to_cls(session)); 1634 iscsi_block_session(session_to_cls(session));
1620 } 1635 }
1621 mutex_unlock(&conn->xmitmutex); 1636 mutex_unlock(&conn->xmitmutex);