diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 55 |
1 files changed, 14 insertions, 41 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index d810acae45f7..963002598995 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -492,7 +492,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) | |||
492 | return; | 492 | return; |
493 | } | 493 | } |
494 | 494 | ||
495 | if (session->conn_cnt == 1 || session->leadconn == conn) | 495 | if (conn->stop_stage == 0) |
496 | session->state = ISCSI_STATE_FAILED; | 496 | session->state = ISCSI_STATE_FAILED; |
497 | spin_unlock_irqrestore(&session->lock, flags); | 497 | spin_unlock_irqrestore(&session->lock, flags); |
498 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 498 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
@@ -652,7 +652,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
652 | */ | 652 | */ |
653 | if (session->state == ISCSI_STATE_IN_RECOVERY) { | 653 | if (session->state == ISCSI_STATE_IN_RECOVERY) { |
654 | reason = FAILURE_SESSION_IN_RECOVERY; | 654 | reason = FAILURE_SESSION_IN_RECOVERY; |
655 | goto fault; | 655 | goto reject; |
656 | } | 656 | } |
657 | 657 | ||
658 | if (session->state == ISCSI_STATE_RECOVERY_FAILED) | 658 | if (session->state == ISCSI_STATE_RECOVERY_FAILED) |
@@ -1411,8 +1411,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1411 | struct iscsi_session *session = conn->session; | 1411 | struct iscsi_session *session = conn->session; |
1412 | unsigned long flags; | 1412 | unsigned long flags; |
1413 | 1413 | ||
1414 | mutex_lock(&conn->xmitmutex); | ||
1415 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | 1414 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); |
1415 | mutex_lock(&conn->xmitmutex); | ||
1416 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { | 1416 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { |
1417 | if (session->tt->suspend_conn_recv) | 1417 | if (session->tt->suspend_conn_recv) |
1418 | session->tt->suspend_conn_recv(conn); | 1418 | session->tt->suspend_conn_recv(conn); |
@@ -1498,7 +1498,6 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1498 | * unblock eh_abort() if it is blocked. re-try all | 1498 | * unblock eh_abort() if it is blocked. re-try all |
1499 | * commands after successful recovery | 1499 | * commands after successful recovery |
1500 | */ | 1500 | */ |
1501 | session->conn_cnt++; | ||
1502 | conn->stop_stage = 0; | 1501 | conn->stop_stage = 0; |
1503 | conn->tmabort_state = TMABORT_INITIAL; | 1502 | conn->tmabort_state = TMABORT_INITIAL; |
1504 | session->age++; | 1503 | session->age++; |
@@ -1508,13 +1507,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1508 | wake_up(&conn->ehwait); | 1507 | wake_up(&conn->ehwait); |
1509 | return 0; | 1508 | return 0; |
1510 | case STOP_CONN_TERM: | 1509 | case STOP_CONN_TERM: |
1511 | session->conn_cnt++; | ||
1512 | conn->stop_stage = 0; | ||
1513 | break; | ||
1514 | case STOP_CONN_SUSPEND: | ||
1515 | conn->stop_stage = 0; | 1510 | conn->stop_stage = 0; |
1516 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); | ||
1517 | clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
1518 | break; | 1511 | break; |
1519 | default: | 1512 | default: |
1520 | break; | 1513 | break; |
@@ -1589,28 +1582,24 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
1589 | 1582 | ||
1590 | /* | 1583 | /* |
1591 | * When this is called for the in_login state, we only want to clean | 1584 | * When this is called for the in_login state, we only want to clean |
1592 | * up the login task and connection. | 1585 | * up the login task and connection. We do not need to block and set |
1586 | * the recovery state again | ||
1593 | */ | 1587 | */ |
1594 | if (conn->stop_stage != STOP_CONN_RECOVER) | 1588 | if (flag == STOP_CONN_TERM) |
1595 | session->conn_cnt--; | 1589 | session->state = ISCSI_STATE_TERMINATE; |
1590 | else if (conn->stop_stage != STOP_CONN_RECOVER) | ||
1591 | session->state = ISCSI_STATE_IN_RECOVERY; | ||
1596 | 1592 | ||
1597 | old_stop_stage = conn->stop_stage; | 1593 | old_stop_stage = conn->stop_stage; |
1598 | conn->stop_stage = flag; | 1594 | conn->stop_stage = flag; |
1595 | conn->c_stage = ISCSI_CONN_STOPPED; | ||
1596 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
1599 | spin_unlock_bh(&session->lock); | 1597 | spin_unlock_bh(&session->lock); |
1600 | 1598 | ||
1601 | if (session->tt->suspend_conn_recv) | 1599 | if (session->tt->suspend_conn_recv) |
1602 | session->tt->suspend_conn_recv(conn); | 1600 | session->tt->suspend_conn_recv(conn); |
1603 | 1601 | ||
1604 | mutex_lock(&conn->xmitmutex); | 1602 | mutex_lock(&conn->xmitmutex); |
1605 | spin_lock_bh(&session->lock); | ||
1606 | conn->c_stage = ISCSI_CONN_STOPPED; | ||
1607 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
1608 | |||
1609 | if (session->conn_cnt == 0 || session->leadconn == conn) | ||
1610 | session->state = ISCSI_STATE_IN_RECOVERY; | ||
1611 | |||
1612 | spin_unlock_bh(&session->lock); | ||
1613 | |||
1614 | /* | 1603 | /* |
1615 | * for connection level recovery we should not calculate | 1604 | * for connection level recovery we should not calculate |
1616 | * header digest. conn->hdr_size used for optimization | 1605 | * header digest. conn->hdr_size used for optimization |
@@ -1620,13 +1609,11 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, | |||
1620 | if (flag == STOP_CONN_RECOVER) { | 1609 | if (flag == STOP_CONN_RECOVER) { |
1621 | conn->hdrdgst_en = 0; | 1610 | conn->hdrdgst_en = 0; |
1622 | conn->datadgst_en = 0; | 1611 | conn->datadgst_en = 0; |
1623 | /* | ||
1624 | * if this is called from the eh and and from userspace | ||
1625 | * then we only need to block once. | ||
1626 | */ | ||
1627 | if (session->state == ISCSI_STATE_IN_RECOVERY && | 1612 | if (session->state == ISCSI_STATE_IN_RECOVERY && |
1628 | old_stop_stage != STOP_CONN_RECOVER) | 1613 | old_stop_stage != STOP_CONN_RECOVER) { |
1614 | debug_scsi("blocking session\n"); | ||
1629 | iscsi_block_session(session_to_cls(session)); | 1615 | iscsi_block_session(session_to_cls(session)); |
1616 | } | ||
1630 | } | 1617 | } |
1631 | 1618 | ||
1632 | session->tt->terminate_conn(conn); | 1619 | session->tt->terminate_conn(conn); |
@@ -1651,20 +1638,6 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | |||
1651 | case STOP_CONN_TERM: | 1638 | case STOP_CONN_TERM: |
1652 | iscsi_start_session_recovery(session, conn, flag); | 1639 | iscsi_start_session_recovery(session, conn, flag); |
1653 | break; | 1640 | break; |
1654 | case STOP_CONN_SUSPEND: | ||
1655 | if (session->tt->suspend_conn_recv) | ||
1656 | session->tt->suspend_conn_recv(conn); | ||
1657 | |||
1658 | mutex_lock(&conn->xmitmutex); | ||
1659 | spin_lock_bh(&session->lock); | ||
1660 | |||
1661 | conn->stop_stage = flag; | ||
1662 | conn->c_stage = ISCSI_CONN_STOPPED; | ||
1663 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
1664 | |||
1665 | spin_unlock_bh(&session->lock); | ||
1666 | mutex_unlock(&conn->xmitmutex); | ||
1667 | break; | ||
1668 | default: | 1641 | default: |
1669 | printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); | 1642 | printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); |
1670 | } | 1643 | } |