[SCSI] iscsi: add libiscsi

There is a lot of code duplcited between iscsi_tcp
and the upcoming iscsi_iser driver. This patch puts
the duplicated code in a lib. There is more code
to move around but this takes care of the
basics. For iscsi_offload if they use the lib we will
probably move some things around. For example in the
queuecommand we will not assume that the LLD wants
to do queue_work, but it is better to handle that
later when we know for sure what iscsi_offload looks
like (we could probably do this for iscsi_iser though to).

Ideally I would like to get the iscsi_transports modules
to a place where all they really have to do is put data
on the wire, but how to do that will hopefully be more clear
when we see other modules like iscsi_offload. Or maybe
iscsi_offload will not use the lib and it will just be
iscsi_iser and iscsi_tcp and maybe the iscsi_tcp_tgt if that
is allowed in mainline.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index e2b67e3..bc9071d 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -472,106 +472,6 @@
 EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
 
 /*
- * These functions are used only by software iscsi_transports
- * which do not allocate and more their scsi_hosts since this
- * is initiated from userspace.
- */
-
-/*
- * iSCSI Session's hostdata organization:
- *
- *    *------------------* <== hostdata_session(host->hostdata)
- *    | ptr to class sess|
- *    |------------------| <== iscsi_hostdata(host->hostdata)
- *    | transport's data |
- *    *------------------*
- */
-
-#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
-				 _t->hostdata_size % sizeof(unsigned long))
-
-#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
-
-/**
- * iscsi_transport_create_session - create iscsi cls session and host
- * scsit: scsi transport template
- * transport: iscsi transport template
- *
- * This can be used by software iscsi_transports that allocate
- * a session per scsi host.
- **/
-struct Scsi_Host *
-iscsi_transport_create_session(struct scsi_transport_template *scsit,
-			       struct iscsi_transport *transport)
-{
-	struct iscsi_cls_session *session;
-	struct Scsi_Host *shost;
-	unsigned long flags;
-
-	shost = scsi_host_alloc(transport->host_template,
-				hostdata_privsize(transport));
-	if (!shost) {
-		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
-			"session\n");
-		return NULL;
-	}
-
-	shost->max_id = 1;
-	shost->max_channel = 0;
-	shost->max_lun = transport->max_lun;
-	shost->max_cmd_len = transport->max_cmd_len;
-	shost->transportt = scsit;
-	shost->transportt->create_work_queue = 1;
-
-	if (scsi_add_host(shost, NULL))
-		goto free_host;
-
-	session = iscsi_create_session(shost, transport, 0);
-	if (!session)
-		goto remove_host;
-
-	*(unsigned long*)shost->hostdata = (unsigned long)session;
-	spin_lock_irqsave(&sesslock, flags);
-	list_add(&session->sess_list, &sesslist);
-	spin_unlock_irqrestore(&sesslock, flags);
-	return shost;
-
-remove_host:
-	scsi_remove_host(shost);
-free_host:
-	scsi_host_put(shost);
-	return NULL;
-}
-
-EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
-
-/**
- * iscsi_transport_destroy_session - destroy session and scsi host
- * shost: scsi host
- *
- * This can be used by software iscsi_transports that allocate
- * a session per scsi host.
- **/
-int iscsi_transport_destroy_session(struct Scsi_Host *shost)
-{
-	struct iscsi_cls_session *session;
-	unsigned long flags;
-
-	session = hostdata_session(shost->hostdata);
-	spin_lock_irqsave(&sesslock, flags);
-	list_del(&session->sess_list);
-	spin_unlock_irqrestore(&sesslock, flags);
-	iscsi_destroy_session(session);
-
-	scsi_remove_host(shost);
-	/* ref from host alloc */
-	scsi_host_put(shost);
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
-
-/*
  * iscsi interface functions
  */
 static struct iscsi_internal *
@@ -857,14 +757,19 @@
 {
 	struct iscsi_transport *transport = priv->iscsi_transport;
 	struct iscsi_cls_session *session;
+	unsigned long flags;
 	uint32_t hostno;
 
-	session = transport->create_session(&priv->t,
+	session = transport->create_session(transport, &priv->t,
 					    ev->u.c_session.initial_cmdsn,
 					    &hostno);
 	if (!session)
 		return -ENOMEM;
 
+	spin_lock_irqsave(&sesslock, flags);
+	list_add(&session->sess_list, &sesslist);
+	spin_unlock_irqrestore(&sesslock, flags);
+
 	ev->r.c_session_ret.host_no = hostno;
 	ev->r.c_session_ret.sid = session->sid;
 	return 0;
@@ -1032,6 +937,7 @@
 	struct iscsi_internal *priv;
 	struct iscsi_cls_session *session;
 	struct iscsi_cls_conn *conn;
+	unsigned long flags;
 
 	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
 	if (!priv)
@@ -1047,9 +953,13 @@
 		break;
 	case ISCSI_UEVENT_DESTROY_SESSION:
 		session = iscsi_session_lookup(ev->u.d_session.sid);
-		if (session)
+		if (session) {
+			spin_lock_irqsave(&sesslock, flags);
+			list_del(&session->sess_list);
+			spin_unlock_irqrestore(&sesslock, flags);
+
 			transport->destroy_session(session);
-		else
+		} else
 			err = -EINVAL;
 		break;
 	case ISCSI_UEVENT_CREATE_CONN: