Commit 98644047 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] libiscsi: fix oops in connection create failure path

If connection creation fails we end up calling list_del
on a invalid struct. This then causes an oops. We are not
acutally using the lists (old MCS code we thought might
be useful elsewhere) so this patch just removes that
code.
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 43a145a3
...@@ -778,6 +778,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) ...@@ -778,6 +778,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
} }
conn = session->leadconn; conn = session->leadconn;
if (!conn) {
reason = FAILURE_SESSION_FREED;
goto fault;
}
if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
sizeof(void*))) { sizeof(void*))) {
...@@ -1377,7 +1381,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, ...@@ -1377,7 +1381,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
} }
spin_lock_init(&session->lock); spin_lock_init(&session->lock);
INIT_LIST_HEAD(&session->connections);
/* initialize immediate command pool */ /* initialize immediate command pool */
if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
...@@ -1580,16 +1583,11 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) ...@@ -1580,16 +1583,11 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
kfree(conn->persistent_address); kfree(conn->persistent_address);
__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
sizeof(void*)); sizeof(void*));
list_del(&conn->item); if (session->leadconn == conn) {
if (list_empty(&session->connections))
session->leadconn = NULL; session->leadconn = NULL;
if (session->leadconn && session->leadconn == conn)
session->leadconn = container_of(session->connections.next,
struct iscsi_conn, item);
if (session->leadconn == NULL)
/* no connections exits.. reset sequencing */ /* no connections exits.. reset sequencing */
session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
}
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
kfifo_free(conn->immqueue); kfifo_free(conn->immqueue);
...@@ -1777,32 +1775,12 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, ...@@ -1777,32 +1775,12 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
struct iscsi_cls_conn *cls_conn, int is_leading) struct iscsi_cls_conn *cls_conn, int is_leading)
{ {
struct iscsi_session *session = class_to_transport_session(cls_session); struct iscsi_session *session = class_to_transport_session(cls_session);
struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; struct iscsi_conn *conn = cls_conn->dd_data;
/* lookup for existing connection */
spin_lock_bh(&session->lock); spin_lock_bh(&session->lock);
list_for_each_entry(tmp, &session->connections, item) {
if (tmp == conn) {
if (conn->c_stage != ISCSI_CONN_STOPPED ||
conn->stop_stage == STOP_CONN_TERM) {
printk(KERN_ERR "iscsi: can't bind "
"non-stopped connection (%d:%d)\n",
conn->c_stage, conn->stop_stage);
spin_unlock_bh(&session->lock);
return -EIO;
}
break;
}
}
if (tmp != conn) {
/* bind new iSCSI connection to session */
conn->session = session;
list_add(&conn->item, &session->connections);
}
spin_unlock_bh(&session->lock);
if (is_leading) if (is_leading)
session->leadconn = conn; session->leadconn = conn;
spin_unlock_bh(&session->lock);
/* /*
* Unblock xmitworker(), Login Phase will pass through. * Unblock xmitworker(), Login Phase will pass through.
......
...@@ -136,7 +136,6 @@ struct iscsi_conn { ...@@ -136,7 +136,6 @@ struct iscsi_conn {
/* control data */ /* control data */
int id; /* CID */ int id; /* CID */
struct list_head item; /* maintains list of conns */
int c_stage; /* connection state */ int c_stage; /* connection state */
/* /*
* Preallocated buffer for pdus that have data but do not * Preallocated buffer for pdus that have data but do not
...@@ -235,10 +234,8 @@ struct iscsi_session { ...@@ -235,10 +234,8 @@ struct iscsi_session {
* - mgmtpool, * * - mgmtpool, *
* - r2tpool */ * - r2tpool */
int state; /* session state */ int state; /* session state */
struct list_head item;
int age; /* counts session re-opens */ int age; /* counts session re-opens */
struct list_head connections; /* list of connections */
int cmds_max; /* size of cmds array */ int cmds_max; /* size of cmds array */
struct iscsi_cmd_task **cmds; /* Original Cmds arr */ struct iscsi_cmd_task **cmds; /* Original Cmds arr */
struct iscsi_queue cmdpool; /* PDU's pool */ struct iscsi_queue cmdpool; /* PDU's pool */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment