[SCSI] iscsi: don't switch states when just cleaning up

If recovery failed or we are in recovery only overwrite the state
if we are going to terminate the session or if we logged back in.

STOP_CONN_SUSPEND and conn_cnt are not used. We only support
a single connection session ATM, so cleanup that code while
we are working around it.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Mike Christie 2006-05-30 00:37:20 -05:00 коммит произвёл James Bottomley
Родитель 9bf0a28c9a
Коммит 67a611149b
3 изменённых файлов: 33 добавлений и 63 удалений

Просмотреть файл

@ -1955,30 +1955,28 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
if (err) if (err)
return err; return err;
if (conn->stop_stage != STOP_CONN_SUSPEND) { /* bind iSCSI connection and socket */
/* bind iSCSI connection and socket */ tcp_conn->sock = sock;
tcp_conn->sock = sock;
/* setup Socket parameters */ /* setup Socket parameters */
sk = sock->sk; sk = sock->sk;
sk->sk_reuse = 1; sk->sk_reuse = 1;
sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */ sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
sk->sk_allocation = GFP_ATOMIC; sk->sk_allocation = GFP_ATOMIC;
/* FIXME: disable Nagle's algorithm */ /* FIXME: disable Nagle's algorithm */
/* /*
* Intercept TCP callbacks for sendfile like receive * Intercept TCP callbacks for sendfile like receive
* processing. * processing.
*/ */
conn->recv_lock = &sk->sk_callback_lock; conn->recv_lock = &sk->sk_callback_lock;
iscsi_conn_set_callbacks(conn); iscsi_conn_set_callbacks(conn);
tcp_conn->sendpage = tcp_conn->sock->ops->sendpage; tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
/* /*
* set receive state machine into initial state * set receive state machine into initial state
*/ */
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
}
return 0; return 0;
} }

Просмотреть файл

@ -492,7 +492,7 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
return; return;
} }
if (session->conn_cnt == 1 || session->leadconn == conn) if (conn->stop_stage == 0)
session->state = ISCSI_STATE_FAILED; session->state = ISCSI_STATE_FAILED;
spin_unlock_irqrestore(&session->lock, flags); spin_unlock_irqrestore(&session->lock, flags);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
@ -652,7 +652,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
*/ */
if (session->state == ISCSI_STATE_IN_RECOVERY) { if (session->state == ISCSI_STATE_IN_RECOVERY) {
reason = FAILURE_SESSION_IN_RECOVERY; reason = FAILURE_SESSION_IN_RECOVERY;
goto fault; goto reject;
} }
if (session->state == ISCSI_STATE_RECOVERY_FAILED) if (session->state == ISCSI_STATE_RECOVERY_FAILED)
@ -1411,8 +1411,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
struct iscsi_session *session = conn->session; struct iscsi_session *session = conn->session;
unsigned long flags; unsigned long flags;
mutex_lock(&conn->xmitmutex);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
mutex_lock(&conn->xmitmutex);
if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
if (session->tt->suspend_conn_recv) if (session->tt->suspend_conn_recv)
session->tt->suspend_conn_recv(conn); session->tt->suspend_conn_recv(conn);
@ -1498,7 +1498,6 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
* unblock eh_abort() if it is blocked. re-try all * unblock eh_abort() if it is blocked. re-try all
* commands after successful recovery * commands after successful recovery
*/ */
session->conn_cnt++;
conn->stop_stage = 0; conn->stop_stage = 0;
conn->tmabort_state = TMABORT_INITIAL; conn->tmabort_state = TMABORT_INITIAL;
session->age++; session->age++;
@ -1508,14 +1507,8 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
wake_up(&conn->ehwait); wake_up(&conn->ehwait);
return 0; return 0;
case STOP_CONN_TERM: case STOP_CONN_TERM:
session->conn_cnt++;
conn->stop_stage = 0; conn->stop_stage = 0;
break; break;
case STOP_CONN_SUSPEND:
conn->stop_stage = 0;
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
break;
default: default:
break; break;
} }
@ -1589,28 +1582,24 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
/* /*
* When this is called for the in_login state, we only want to clean * When this is called for the in_login state, we only want to clean
* up the login task and connection. * up the login task and connection. We do not need to block and set
* the recovery state again
*/ */
if (conn->stop_stage != STOP_CONN_RECOVER) if (flag == STOP_CONN_TERM)
session->conn_cnt--; session->state = ISCSI_STATE_TERMINATE;
else if (conn->stop_stage != STOP_CONN_RECOVER)
session->state = ISCSI_STATE_IN_RECOVERY;
old_stop_stage = conn->stop_stage; old_stop_stage = conn->stop_stage;
conn->stop_stage = flag; conn->stop_stage = flag;
conn->c_stage = ISCSI_CONN_STOPPED;
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
if (session->tt->suspend_conn_recv) if (session->tt->suspend_conn_recv)
session->tt->suspend_conn_recv(conn); session->tt->suspend_conn_recv(conn);
mutex_lock(&conn->xmitmutex); mutex_lock(&conn->xmitmutex);
spin_lock_bh(&session->lock);
conn->c_stage = ISCSI_CONN_STOPPED;
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
if (session->conn_cnt == 0 || session->leadconn == conn)
session->state = ISCSI_STATE_IN_RECOVERY;
spin_unlock_bh(&session->lock);
/* /*
* for connection level recovery we should not calculate * for connection level recovery we should not calculate
* header digest. conn->hdr_size used for optimization * header digest. conn->hdr_size used for optimization
@ -1620,13 +1609,11 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
if (flag == STOP_CONN_RECOVER) { if (flag == STOP_CONN_RECOVER) {
conn->hdrdgst_en = 0; conn->hdrdgst_en = 0;
conn->datadgst_en = 0; conn->datadgst_en = 0;
/*
* if this is called from the eh and and from userspace
* then we only need to block once.
*/
if (session->state == ISCSI_STATE_IN_RECOVERY && if (session->state == ISCSI_STATE_IN_RECOVERY &&
old_stop_stage != STOP_CONN_RECOVER) old_stop_stage != STOP_CONN_RECOVER) {
debug_scsi("blocking session\n");
iscsi_block_session(session_to_cls(session)); iscsi_block_session(session_to_cls(session));
}
} }
session->tt->terminate_conn(conn); session->tt->terminate_conn(conn);
@ -1651,20 +1638,6 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
case STOP_CONN_TERM: case STOP_CONN_TERM:
iscsi_start_session_recovery(session, conn, flag); iscsi_start_session_recovery(session, conn, flag);
break; break;
case STOP_CONN_SUSPEND:
if (session->tt->suspend_conn_recv)
session->tt->suspend_conn_recv(conn);
mutex_lock(&conn->xmitmutex);
spin_lock_bh(&session->lock);
conn->stop_stage = flag;
conn->c_stage = ISCSI_CONN_STOPPED;
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
spin_unlock_bh(&session->lock);
mutex_unlock(&conn->xmitmutex);
break;
default: default:
printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
} }

Просмотреть файл

@ -211,7 +211,6 @@ struct iscsi_session {
* - r2tpool */ * - r2tpool */
int state; /* session state */ int state; /* session state */
struct list_head item; struct list_head item;
int conn_cnt;
int age; /* counts session re-opens */ int age; /* counts session re-opens */
struct list_head connections; /* list of connections */ struct list_head connections; /* list of connections */