Mike Christie wrote:
> On 09/01/2009 09:53 AM, Mike Christie wrote:
>> On 09/01/2009 03:58 AM, Or Gerlitz wrote:
>>> Mike Christie wrote:
>>>> Or, I am ccing you because some time ago Erez was working on support
>>>> for older RHEL and SLES kernels for OFED. It looks like the patch
>>>> below would not be useful to you because iser is supported in those
>>>> kernels, but did you guys all need RHEL 4 and maybe SLES 9 support too?
>>> Hi Mike, I'm used to work with patches which have a change log and are
>>> signed, where this patch lacks both, so I can't really understand what
>>> it is about, sorry.
>>>
>>
>> A signature is not going to help you understand that patch will it? :)
>>
>> I do not think a changelog will help either since it is the first
>> version of a RFC patch.
>>
>>   From the subject of the mail and the body it looks like Rakesh is
>> trying to port libiscsi to older distro kernels (RHEL 5 and SLES 10
>> based) so he can support cxgb3i on them.
>>
>> I am just asking you guys if you also need RHEL 4 and SLES 9 support.
>>
> 
> You guys meaning, do you need iser and does Rakesh need cxgb3i?

Hi Mike,

Yes we do want to support cxgb3i on RHEL4/SLES9. I am sending the 
modified patch against current james tree's libiscsi part. This patch 
can replace existing 2.6.14-23_compat.patch.

Regards
Rakesh Ranjan

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to 
open-iscsi+unsubscr...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

>From 3e33dcf314395c77dbe02c32602a8c9212136b46 Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rran...@chelsio.com>
Date: Thu, 3 Sep 2009 17:23:10 +0530
Subject: [RFC] libiscsi port to support cxgb3i on older RHEL/SLES


Signed-off-by: Rakesh Ranjan <rran...@chelsio.com>
---
 kernel/iscsi_tcp.c            |   18 +--
 kernel/iscsi_tcp.h            |    1 +
 kernel/libiscsi.c             |   92 ++++++++---
 kernel/libiscsi.h             |    6 +-
 kernel/libiscsi_tcp.c         |   29 +++-
 kernel/open_iscsi_compat.h    |  360 +++++++++++++++++++++++++++++++++++++++++
 kernel/scsi_transport_iscsi.c |  272 +++++++++++++++----------------
 kernel/scsi_transport_iscsi.h |    7 +-
 8 files changed, 600 insertions(+), 185 deletions(-)
 create mode 100644 kernel/open_iscsi_compat.h

diff --git a/kernel/iscsi_tcp.c b/kernel/iscsi_tcp.c
index 61e5018..b05801f 100644
--- a/kernel/iscsi_tcp.c
+++ b/kernel/iscsi_tcp.c
@@ -459,10 +459,9 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
 	if (!task->sc)
 		iscsi_sw_tcp_send_linear_data_prep(conn, task->data, count);
 	else {
-		struct scsi_data_buffer *sdb = scsi_out(task->sc);
 
-		err = iscsi_sw_tcp_send_data_prep(conn, sdb->table.sgl,
-						  sdb->table.nents, offset,
+		err = iscsi_sw_tcp_send_data_prep(conn, scsi_sglist(task->sc),
+						  scsi_sg_count(task->sc), offset,
 						  count);
 	}
 
@@ -608,14 +607,14 @@ static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
 	case AF_INET:
 		sin = (struct sockaddr_in *)addr;
 		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, "%pI4", &sin->sin_addr.s_addr);
+		sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
 		*port = be16_to_cpu(sin->sin_port);
 		spin_unlock_bh(&conn->session->lock);
 		break;
 	case AF_INET6:
 		sin6 = (struct sockaddr_in6 *)addr;
 		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, "%pI6", &sin6->sin6_addr);
+		sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr));
 		*port = be16_to_cpu(sin6->sin6_port);
 		spin_unlock_bh(&conn->session->lock);
 		break;
@@ -827,12 +826,6 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
 	iscsi_host_free(shost);
 }
 
-static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
-{
-	set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
-	return 0;
-}
-
 static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
 {
 	blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
@@ -851,9 +844,8 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
 	.eh_abort_handler       = iscsi_eh_abort,
 	.eh_device_reset_handler= iscsi_eh_device_reset,
-	.eh_target_reset_handler= iscsi_eh_target_reset,
+	.eh_host_reset_handler	= iscsi_eh_target_reset,
 	.use_clustering         = DISABLE_CLUSTERING,
-	.slave_alloc            = iscsi_sw_tcp_slave_alloc,
 	.slave_configure        = iscsi_sw_tcp_slave_configure,
 	.target_alloc		= iscsi_target_alloc,
 	.proc_name		= "iscsi_tcp",
diff --git a/kernel/iscsi_tcp.h b/kernel/iscsi_tcp.h
index f9a4044..5327cfa 100644
--- a/kernel/iscsi_tcp.h
+++ b/kernel/iscsi_tcp.h
@@ -22,6 +22,7 @@
 #ifndef ISCSI_SW_TCP_H
 #define ISCSI_SW_TCP_H
 
+#include "open_iscsi_compat.h"
 #include "libiscsi.h"
 #include "libiscsi_tcp.h"
 
diff --git a/kernel/libiscsi.c b/kernel/libiscsi.c
index 8808779..e2e80ad 100644
--- a/kernel/libiscsi.c
+++ b/kernel/libiscsi.c
@@ -34,6 +34,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_transport.h>
+#include "open_iscsi_compat.h"
 #include "iscsi_proto.h"
 #include "scsi_transport_iscsi.h"
 #include "libiscsi.h"
@@ -252,7 +253,7 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
 						  sizeof(rlen_ahdr->reserved));
 	rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
 	rlen_ahdr->reserved = 0;
-	rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
+	rlen_ahdr->read_length = cpu_to_be32(scsi_bufflen(sc));
 
 	ISCSI_DBG_SESSION(task->conn->session,
 			  "bidi-in rlen_ahdr->read_length(%d) "
@@ -323,7 +324,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
 			return rc;
 	}
 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
-		unsigned out_len = scsi_out(sc)->length;
+		unsigned out_len = scsi_bufflen(sc);
 		struct iscsi_r2t_info *r2t = &task->unsol_r2t;
 
 		hdr->data_length = cpu_to_be32(out_len);
@@ -369,7 +370,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
 	} else {
 		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
 		zero_data(hdr->dlength);
-		hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+		hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
 
 		if (sc->sc_data_direction == DMA_FROM_DEVICE)
 			hdr->flags |= ISCSI_FLAG_CMD_READ;
@@ -396,7 +397,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
 			  sc->sc_data_direction == DMA_TO_DEVICE ?
 			  "write" : "read", conn->id, sc, sc->cmnd[0],
 			  task->itt, scsi_bufflen(sc),
-			  scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+			  scsi_bidi_cmnd(sc) ? scsi_bufflen(sc) : 0,
 			  session->cmdsn,
 			  session->max_cmdsn - session->exp_cmdsn + 1);
 	return 0;
@@ -533,12 +534,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
 		state = ISCSI_TASK_ABRT_TMF;
 
 	sc->result = err << 16;
-	if (!scsi_bidi_cmnd(sc))
-		scsi_set_resid(sc, scsi_bufflen(sc));
-	else {
-		scsi_out(sc)->resid = scsi_out(sc)->length;
-		scsi_in(sc)->resid = scsi_in(sc)->length;
-	}
+	scsi_set_resid(sc, scsi_bufflen(sc));
 
 	iscsi_complete_task(task, state);
 }
@@ -729,7 +725,7 @@ invalid_datalen:
 			goto out;
 		}
 
-		senselen = get_unaligned_be16(data);
+		senselen = be16_to_cpu(get_unaligned((__be16 *) data));
 		if (datalen < senselen)
 			goto invalid_datalen;
 
@@ -746,8 +742,8 @@ invalid_datalen:
 
 		if (scsi_bidi_cmnd(sc) && res_count > 0 &&
 				(rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
-				 res_count <= scsi_in(sc)->length))
-			scsi_in(sc)->resid = res_count;
+				 res_count <= scsi_bufflen(sc)))
+			scsi_set_resid(sc, res_count);
 		else
 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
 	}
@@ -796,8 +792,8 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 
 		if (res_count > 0 &&
 		    (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
-		     res_count <= scsi_in(sc)->length))
-			scsi_in(sc)->resid = res_count;
+		     res_count <= scsi_bufflen(sc)))
+			scsi_set_resid(sc, res_count);
 		else
 			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
 	}
@@ -977,7 +973,9 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 		task = iscsi_itt_to_ctask(conn, hdr->itt);
 		if (!task)
 			return ISCSI_ERR_BAD_ITT;
+#if !(defined RHELC1) && !(defined SLEC1)
 		task->last_xfer = jiffies;
+#endif
 		break;
 	case ISCSI_OP_R2T:
 		/*
@@ -1216,12 +1214,21 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
 	spin_unlock_bh(&conn->session->lock);
 	rc = conn->session->tt->xmit_task(task);
 	spin_lock_bh(&conn->session->lock);
+#if ((defined RHELC1) || (defined SLEC1))
+	__iscsi_put_task(task);
+	if (!rc) {
+		/* done with this task */
+		conn->task = NULL;
+	}
+#else
 	if (!rc) {
 		/* done with this task */
 		task->last_xfer = jiffies;
 		conn->task = NULL;
 	}
+
 	__iscsi_put_task(task);
+#endif
 	return rc;
 }
 
@@ -1387,9 +1394,11 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
 	task->state = ISCSI_TASK_PENDING;
 	task->conn = conn;
 	task->sc = sc;
+#if !((defined RHELC1) && !(defined SLEC1))
 	task->have_checked_conn = false;
 	task->last_timeout = jiffies;
 	task->last_xfer = jiffies;
+#endif
 	INIT_LIST_HEAD(&task->running);
 	return task;
 }
@@ -1518,7 +1527,11 @@ reject:
 	ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
 			  sc->cmnd[0], reason);
 	spin_lock(host->host_lock);
+#if ((defined RHELC1) || (defined SLEC1))
+	return SCSI_MLQUEUE_DEVICE_BUSY;
+#else
 	return SCSI_MLQUEUE_TARGET_BUSY;
+#endif
 
 prepd_fault:
 	sc->scsi_done = NULL;
@@ -1527,12 +1540,7 @@ fault:
 	spin_unlock(&session->lock);
 	ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
 			  sc->cmnd[0], reason);
-	if (!scsi_bidi_cmnd(sc))
-		scsi_set_resid(sc, scsi_bufflen(sc));
-	else {
-		scsi_out(sc)->resid = scsi_out(sc)->length;
-		scsi_in(sc)->resid = scsi_in(sc)->length;
-	}
+	scsi_set_resid(sc, scsi_bufflen(sc));
 	done(sc);
 	spin_lock(host->host_lock);
 	return 0;
@@ -1551,7 +1559,9 @@ int iscsi_target_alloc(struct scsi_target *starget)
 	struct iscsi_cls_session *cls_session = starget_to_session(starget);
 	struct iscsi_session *session = cls_session->dd_data;
 
+#if 0
 	starget->can_queue = session->scsi_cmds_max;
+#endif
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_target_alloc);
@@ -1570,13 +1580,11 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
 }
 EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
 
-int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+int iscsi_target_reset(struct iscsi_cls_session *cls_session)
 {
-	struct iscsi_cls_session *cls_session;
 	struct iscsi_session *session;
 	struct iscsi_conn *conn;
 
-	cls_session = starget_to_session(scsi_target(sc->device));
 	session = cls_session->dd_data;
 	conn = session->leadconn;
 
@@ -1620,6 +1628,15 @@ failed:
 	mutex_unlock(&session->eh_mutex);
 	return SUCCESS;
 }
+EXPORT_SYMBOL_GPL(iscsi_target_reset);
+
+int iscsi_eh_target_reset(struct scsi_cmnd *sc)
+{
+	struct iscsi_cls_session *cls_session;
+
+	cls_session = starget_to_session(scsi_target(sc->device));
+	return iscsi_target_reset(cls_session);
+}
 EXPORT_SYMBOL_GPL(iscsi_eh_target_reset);
 
 static void iscsi_tmf_timedout(unsigned long data)
@@ -1748,7 +1765,10 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
 static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 {
 	enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
+
+#if !(defined RHELC1) && !(defined SLEC1)
 	struct iscsi_task *task = NULL;
+#endif
 	struct iscsi_cls_session *cls_session;
 	struct iscsi_session *session;
 	struct iscsi_conn *conn;
@@ -1775,6 +1795,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 		goto done;
 	}
 
+#if !(defined RHELC1) && !(defined SLEC1)
 	task = (struct iscsi_task *)sc->SCp.ptr;
 	if (!task)
 		goto done;
@@ -1794,6 +1815,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 		rc = BLK_EH_RESET_TIMER;
 		goto done;
 	}
+#endif
 
 	if (!conn->recv_timeout && !conn->ping_timeout)
 		goto done;
@@ -1806,6 +1828,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 		goto done;
 	}
 
+#if !(defined RHELC1) && !(defined SLEC1)
 	/* Assumes nop timeout is shorter than scsi cmd timeout */
 	if (task->have_checked_conn)
 		goto done;
@@ -1819,15 +1842,34 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 		rc = BLK_EH_RESET_TIMER;
 		goto done;
 	}
+#else
+	/*
+	 * if we are about to check the transport then give the command
+	 * more time
+	 */
+	if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
+				jiffies)) {
+		rc = BLK_EH_RESET_TIMER;
+		goto done;
+	}
+#endif
+
 
+#if !(defined RHELC1) && !(defined SLEC1)
 	/* Make sure there is a transport check done */
 	iscsi_send_nopout(conn, NULL);
 	task->have_checked_conn = true;
 	rc = BLK_EH_RESET_TIMER;
-
+#else
+	/*  if in the middle of checking the transport then give us more time */
+	if (conn->ping_task)
+		rc = BLK_EH_RESET_TIMER;
+#endif
 done:
+#if !(defined RHELC1) && !(defined SLEC1)
 	if (task)
 		task->last_timeout = jiffies;
+#endif
 	spin_unlock(&session->lock);
 	ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
 		     "timer reset" : "nh");
diff --git a/kernel/libiscsi.h b/kernel/libiscsi.h
index b6dd8a7..93b0fca 100644
--- a/kernel/libiscsi.h
+++ b/kernel/libiscsi.h
@@ -31,12 +31,13 @@
 #include "iscsi_proto.h"
 #include "iscsi_if.h"
 #include "scsi_transport_iscsi.h"
+#include "open_iscsi_compat.h"
 
 struct scsi_transport_template;
 struct scsi_host_template;
 struct scsi_device;
 struct Scsi_Host;
-struct scsi_target;
+//struct scsi_target;
 struct scsi_cmnd;
 struct socket;
 struct iscsi_transport;
@@ -125,10 +126,12 @@ struct iscsi_task {
 	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
 	struct iscsi_conn	*conn;		/* used connection    */
 
+#if !defined RHELC1 && !defined SLEC1
 	/* data processing tracking */
 	unsigned long		last_xfer;
 	unsigned long		last_timeout;
 	bool			have_checked_conn;
+#endif
 	/* state set/tested under session->lock */
 	int			state;
 	atomic_t		refcount;
@@ -335,6 +338,7 @@ struct iscsi_host {
 extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
 extern int iscsi_eh_abort(struct scsi_cmnd *sc);
 extern int iscsi_eh_target_reset(struct scsi_cmnd *sc);
+extern int iscsi_target_reset(struct iscsi_cls_session *cls_session);
 extern int iscsi_eh_device_reset(struct scsi_cmnd *sc);
 extern int iscsi_queuecommand(struct scsi_cmnd *sc,
 			      void (*done)(struct scsi_cmnd *));
diff --git a/kernel/libiscsi_tcp.c b/kernel/libiscsi_tcp.c
index 4051e62..cf1a961 100644
--- a/kernel/libiscsi_tcp.c
+++ b/kernel/libiscsi_tcp.c
@@ -40,9 +40,9 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi.h>
+#include "open_iscsi_compat.h"
 #include "scsi_transport_iscsi.h"
-
-#include "iscsi_tcp.h"
+#include "libiscsi_tcp.h"
 
 MODULE_AUTHOR("Mike Christie <micha...@cs.wisc.edu>, "
 	      "Dmitry Yusupov <dmitry_...@yahoo.com>, "
@@ -360,6 +360,16 @@ iscsi_segment_seek_sg(struct iscsi_segment *segment,
 	struct scatterlist *sg;
 	unsigned int i;
 
+	/*
+	 * older kernels could send use_sg=0 for commands like sgio
+	 * or scsi-ml commands.
+	 */
+	if (!sg_count) {
+		iscsi_segment_init_linear(segment, (void *)sg_list + offset,
+					size, done, hash);
+		return 0;
+	}
+
 	__iscsi_segment_init(segment, size, done, hash);
 	for_each_sg(sg_list, sg, sg_count, i) {
 		if (offset < sg->length) {
@@ -471,7 +481,7 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
 	struct iscsi_tcp_task *tcp_task = task->dd_data;
 	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
 	int datasn = be32_to_cpu(rhdr->datasn);
-	unsigned total_in_length = scsi_in(task->sc)->length;
+	unsigned total_in_length = scsi_bufflen(task->sc);
 
 	/*
 	 * lib iscsi will update this in the completion handling if there
@@ -565,11 +575,11 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
 			      r2t->data_length, session->max_burst);
 
 	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
-	if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
+	if (r2t->data_offset + r2t->data_length > scsi_bufflen(task->sc)) {
 		iscsi_conn_printk(KERN_ERR, conn,
 				  "invalid R2T with data len %u at offset %u "
 				  "and total length %d\n", r2t->data_length,
-				  r2t->data_offset, scsi_out(task->sc)->length);
+				  r2t->data_offset, scsi_bufflen(task->sc));
 		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
 			    sizeof(void*));
 		return ISCSI_ERR_DATALEN;
@@ -668,7 +678,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
 		if (tcp_conn->in.datalen) {
 			struct iscsi_tcp_task *tcp_task = task->dd_data;
 			struct hash_desc *rx_hash = NULL;
-			struct scsi_data_buffer *sdb = scsi_in(task->sc);
 
 			/*
 			 * Setup copy of Data-In into the Scsi_Cmnd
@@ -686,10 +695,12 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
 				     "offset=%d, datalen=%d)\n",
 				      tcp_task->data_offset,
 				      tcp_conn->in.datalen);
+#if !(defined RHELC1) && !(defined SLEC1)
 			task->last_xfer = jiffies;
+#endif
 			rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
-						   sdb->table.sgl,
-						   sdb->table.nents,
+						   scsi_sglist(task->sc),
+						   scsi_sg_count(task->sc),
 						   tcp_task->data_offset,
 						   tcp_conn->in.datalen,
 						   iscsi_tcp_process_data_in,
@@ -715,7 +726,9 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
 		else if (ahslen)
 			rc = ISCSI_ERR_AHSLEN;
 		else if (task->sc->sc_data_direction == DMA_TO_DEVICE) {
+#if !(defined RHELC1) && !(defined SLEC1)
 			task->last_xfer = jiffies;
+#endif
 			rc = iscsi_tcp_r2t_rsp(conn, task);
 		} else
 			rc = ISCSI_ERR_PROTO;
diff --git a/kernel/open_iscsi_compat.h b/kernel/open_iscsi_compat.h
new file mode 100644
index 0000000..ff5e88f
--- /dev/null
+++ b/kernel/open_iscsi_compat.h
@@ -0,0 +1,360 @@
+#ifndef OPEN_ISCSI_COMPAT
+#define OPEN_ISCSI_COMPAT
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+
+#ifndef SCAN_WILD_CARD
+#define SCAN_WILD_CARD  ~0
+#endif
+
+#ifndef NIPQUAD_FMT
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+#endif
+
+#ifndef NIP6_FMT
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#endif
+
+#ifndef DEFINE_MUTEX
+
+/* mutex changes from 2.6.16-rc1 and up */
+#define DEFINE_MUTEX DECLARE_MUTEX
+#define mutex_lock down
+#define mutex_unlock up
+#define mutex semaphore
+#define mutex_init init_MUTEX
+#endif
+
+#ifdef RHEL_RELEASE_CODE
+#if (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 4))
+#define RHELC1	1
+#endif
+#endif
+
+#ifdef SLE_VERSION_CODE
+#if (SLE_VERSION_CODE < SLE_VERSION(11, 0, 0))
+#define SLEC1	1
+#endif
+#endif
+
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,19) 
+#if !(defined RHELC1) && !(defined SLEC1)
+struct delayed_work {
+	struct work_struct work;
+};
+
+#define cancel_delayed_work(_dwork) cancel_delayed_work(&(_dwork)->work)
+#define INIT_DELAYED_WORK(_work,_func) INIT_WORK(&(_work)->work, _func)
+#endif
+
+static inline void INIT_WORK_compat(struct work_struct *work, void *func)
+{
+	INIT_WORK(work, func, work);
+}
+
+#undef INIT_WORK
+#define INIT_WORK(_work, _func) INIT_WORK_compat(_work, _func)
+#if !(defined INIT_DELAYED_WORK)
+#define INIT_DELAYED_WORK(_work,_func) INIT_WORK_compat(_work, _func)
+#endif
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
+
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+	int i;
+
+	memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+	for (i = 0; i < sizeof(lun); i += 2) {
+		scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+		scsilun->scsi_lun[i+1] = lun & 0xFF;
+		lun = lun >> 16;
+	}
+}
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+	__nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) && \
+	RHEL_RELEASE_CODE != RHEL_RELEASE_VERSION(4,8)
+
+#define gfp_t unsigned
+
+void *kzalloc(size_t size, gfp_t flags)
+{
+	void *ret = kmalloc(size, flags);
+	if (ret)
+		memset(ret, 0, size);
+}
+
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+
+#include "linux/crypto.h"
+
+#if !defined SLEC1
+#define CRYPTO_ALG_ASYNC		0x00000080
+struct hash_desc
+{
+	struct crypto_tfm *tfm;
+	u32 flags;
+};
+
+static inline int crypto_hash_init(struct hash_desc *desc)
+{
+	crypto_digest_init(desc->tfm);
+	return 0;
+}
+
+static inline int crypto_hash_digest(struct hash_desc *desc,
+				     struct scatterlist *sg,
+				     unsigned int nbytes, u8 *out)
+{
+	crypto_digest_digest(desc->tfm, sg, 1, out);
+	return nbytes;
+}
+
+static inline int crypto_hash_update(struct hash_desc *desc,
+				     struct scatterlist *sg,
+				     unsigned int nbytes)
+{
+	crypto_digest_update(desc->tfm, sg, 1);
+	return nbytes;
+}
+
+static inline int crypto_hash_final(struct hash_desc *desc, u8 *out)
+{
+	crypto_digest_final(desc->tfm, out);
+	return 0;
+}
+
+static inline struct crypto_tfm *crypto_alloc_hash(const char *alg_name,
+						    u32 type, u32 mask)
+{
+	struct crypto_tfm *ret = crypto_alloc_tfm(alg_name ,type);
+	return ret ? ret : ERR_PTR(-ENOMEM);
+}
+
+static inline void crypto_free_hash(struct crypto_tfm *tfm)
+{
+	crypto_free_tfm(tfm);
+}
+#endif
+#ifdef RHEL_RELEASE_VERSION
+#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,1)
+static inline int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
+			int *addrlen)
+{
+	return sock->ops->getname(sock, addr, addrlen, 0);
+}
+
+static inline int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
+			int *addrlen)
+{
+	return sock->ops->getname(sock, addr, addrlen, 1);
+}
+#endif
+#endif
+#endif
+
+#ifndef bool
+#define bool int
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20)
+#ifdef RHEL_RELEASE_VERSION
+#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2) && \
+	RHEL_RELEASE_CODE != RHEL_RELEASE_VERSION(4,8)
+static inline int is_power_of_2(unsigned long n)
+{
+	return (n != 0 && ((n & (n - 1)) == 0));
+}
+#endif
+#else
+/* not a redhat kernel */
+static inline int is_power_of_2(unsigned long n)
+{
+	return (n != 0 && ((n & (n - 1)) == 0));
+}
+#endif
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
+
+static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
+{
+	return (struct nlmsghdr *)skb->data;
+}
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
+#ifdef RHEL_RELEASE_VERSION
+#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2)
+static inline void *shost_priv(struct Scsi_Host *shost)
+{
+	return (void *)shost->hostdata;
+}
+#endif
+#else
+/* not a redhat kernel */
+static inline void *shost_priv(struct Scsi_Host *shost)
+{
+	return (void *)shost->hostdata;
+}
+#endif
+
+/*
+ * Note: We do not support bidi for the compat modules if the kernel
+ * does not have support.
+ */
+#define scsi_sg_count(cmd) ((cmd)->use_sg)
+#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
+#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+
+#ifdef RHEL_RELEASE_VERSION
+#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2)
+static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
+{
+	cmd->resid = resid;
+}
+
+static inline int scsi_get_resid(struct scsi_cmnd *cmd)
+{
+	return cmd->resid;
+}
+#endif
+#else
+/* not a redhat kernel */
+static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
+{
+	cmd->resid = resid;
+}
+
+static inline int scsi_get_resid(struct scsi_cmnd *cmd)
+{
+	return cmd->resid;
+}
+#endif
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
+
+#ifdef	SLE_VERSION_CODE
+#if SLE_VERSION_CODE == SLE_VERSION(10,2,0)
+ 
+static inline unsigned fls_long(unsigned long l)
+{
+	if (sizeof(l) == 4)
+		return fls(l);
+	return fls64(l);
+}
+
+#endif
+#endif
+
+static inline unsigned long rounddown_pow_of_two(unsigned long n)
+{
+	return 1UL << (fls_long(n) - 1);
+}
+
+
+static inline struct scatterlist *sg_next(struct scatterlist *sg)
+{
+	if (!sg) {
+		BUG();
+		return NULL;
+	}
+	return sg + 1;
+}
+
+#define for_each_sg(sglist, sg, nr, __i)        \
+	for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
+
+#define sg_page(_sg) _sg->page
+
+static inline void sg_set_page(struct scatterlist *sg, struct page *page,
+				unsigned int len, unsigned int offset)
+{
+	sg->page = page;
+	sg->offset = offset;
+	sg->length = len;
+}
+
+static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
+{
+	memset(sgl, 0, sizeof(*sgl) * nents);
+}
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
+
+static inline int scsi_bidi_cmnd(struct scsi_cmnd *cmd)
+{
+	return 0;
+}
+
+#define netlink_kernel_release(_nls) \
+	sock_release(_nls->sk_socket)
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
+
+#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
+	netlink_kernel_create(uint, groups, input, cb_mutex, mod)
+
+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,19)
+
+#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
+	netlink_kernel_create(uint, groups, input, mod)
+
+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
+
+#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
+	netlink_kernel_create(uint, groups, input, cb_mutex, mod)
+
+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
+
+#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
+	netlink_kernel_create(uint, groups, input, cb_mutex, mod)
+
+#endif
+
+#ifndef DID_TRANSPORT_DISRUPTED
+#define DID_TRANSPORT_DISRUPTED DID_BUS_BUSY
+#endif
+
+#ifndef DID_TRANSPORT_FAILFAST
+#define DID_TRANSPORT_FAILFAST DID_NO_CONNECT
+#endif
+
+#ifndef SCSI_MLQUEUE_TARGET_BUSY
+#define SCSI_MLQUEUE_TARGET_BUSY SCSI_MLQUEUE_HOST_BUSY
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)
+
+#define BLK_EH_NOT_HANDLED EH_NOT_HANDLED
+#define BLK_EH_RESET_TIMER EH_RESET_TIMER
+
+#define blk_eh_timer_return scsi_eh_timer_return
+
+#endif
+
+#ifndef	SCSI_MAX_VARLEN_CDB_SIZE
+#define	SCSI_MAX_VARLEN_CDB_SIZE 16
+#endif
+
+#endif
diff --git a/kernel/scsi_transport_iscsi.c b/kernel/scsi_transport_iscsi.c
index 6cbeefa..8ef6d45 100644
--- a/kernel/scsi_transport_iscsi.c
+++ b/kernel/scsi_transport_iscsi.c
@@ -40,13 +40,13 @@ struct iscsi_internal {
 	struct scsi_transport_template t;
 	struct iscsi_transport *iscsi_transport;
 	struct list_head list;
-	struct device dev;
+	struct class_device cdev;
 
-	struct device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
+	struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
 	struct transport_container conn_cont;
-	struct device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
+	struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
 	struct transport_container session_cont;
-	struct device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
+	struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
 };
 
 static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
@@ -63,12 +63,12 @@ static DEFINE_SPINLOCK(iscsi_transport_lock);
 #define to_iscsi_internal(tmpl) \
 	container_of(tmpl, struct iscsi_internal, t)
 
-#define dev_to_iscsi_internal(_dev) \
-	container_of(_dev, struct iscsi_internal, dev)
+#define cdev_to_iscsi_internal(_cdev) \
+	container_of(_cdev, struct iscsi_internal, cdev)
 
-static void iscsi_transport_release(struct device *dev)
+static void iscsi_transport_release(struct class_device *cdev)
 {
-	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
 	kfree(priv);
 }
 
@@ -78,33 +78,31 @@ static void iscsi_transport_release(struct device *dev)
  */
 static struct class iscsi_transport_class = {
 	.name = "iscsi_transport",
-	.dev_release = iscsi_transport_release,
+	.release = iscsi_transport_release,
 };
 
 static ssize_t
-show_transport_handle(struct device *dev, struct device_attribute *attr,
-		      char *buf)
+show_transport_handle(struct class_device *cdev, char *buf)
 {
-	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
+	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
 	return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
 }
-static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
+static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
 
 #define show_transport_attr(name, format)				\
 static ssize_t								\
-show_transport_##name(struct device *dev, 				\
-		      struct device_attribute *attr,char *buf)		\
+show_transport_##name(struct class_device *cdev, char *buf)		\
 {									\
-	struct iscsi_internal *priv = dev_to_iscsi_internal(dev);	\
+	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);	\
 	return sprintf(buf, format"\n", priv->iscsi_transport->name);	\
 }									\
-static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
 
 show_transport_attr(caps, "0x%x");
 
 static struct attribute *iscsi_transport_attrs[] = {
-	&dev_attr_handle.attr,
-	&dev_attr_caps.attr,
+	&class_device_attr_handle.attr,
+	&class_device_attr_caps.attr,
 	NULL,
 };
 
@@ -122,27 +120,30 @@ static struct attribute_group iscsi_transport_group = {
 struct device_attribute dev_attr_##_prefix##_##_name =	\
         __ATTR(_name,_mode,_show,_store)
 
-static void iscsi_endpoint_release(struct device *dev)
+static void iscsi_endpoint_release(struct class_device *cdev)
 {
-	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
+	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(cdev);
 	kfree(ep);
 }
 
 static struct class iscsi_endpoint_class = {
 	.name = "iscsi_endpoint",
-	.dev_release = iscsi_endpoint_release,
+	.release = iscsi_endpoint_release,
 };
 
 static ssize_t
-show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
+show_ep_handle(struct class_device *cdev, char *buf)
 {
-	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
+	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(cdev);
 	return sprintf(buf, "%llu\n", (unsigned long long) ep->id);
 }
-static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
+
+static struct class_device_attribute class_device_attr_ep_handle =
+	__ATTR(handle, S_IRUGO, show_ep_handle, NULL);
+
 
 static struct attribute *iscsi_endpoint_attrs[] = {
-	&dev_attr_ep_handle.attr,
+	&class_device_attr_ep_handle.attr,
 	NULL,
 };
 
@@ -152,26 +153,15 @@ static struct attribute_group iscsi_endpoint_group = {
 
 #define ISCSI_MAX_EPID -1
 
-static int iscsi_match_epid(struct device *dev, void *data)
-{
-	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
-	uint64_t *epid = (uint64_t *) data;
-
-	return *epid == ep->id;
-}
-
 struct iscsi_endpoint *
 iscsi_create_endpoint(int dd_size)
 {
-	struct device *dev;
 	struct iscsi_endpoint *ep;
 	uint64_t id;
 	int err;
 
 	for (id = 1; id < ISCSI_MAX_EPID; id++) {
-		dev = class_find_device(&iscsi_endpoint_class, NULL, &id,
-					iscsi_match_epid);
-		if (!dev)
+		if (!iscsi_lookup_endpoint(id))
 			break;
 	}
 	if (id == ISCSI_MAX_EPID) {
@@ -186,8 +176,9 @@ iscsi_create_endpoint(int dd_size)
 
 	ep->id = id;
 	ep->dev.class = &iscsi_endpoint_class;
-	dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id);
-	err = device_register(&ep->dev);
+	snprintf(ep->dev.class_id, BUS_ID_SIZE, "ep-%llu",
+			(unsigned long long) id);
+	err = class_device_register(&ep->dev);
         if (err)
                 goto free_ep;
 
@@ -200,7 +191,7 @@ iscsi_create_endpoint(int dd_size)
 	return ep;
 
 unregister_dev:
-	device_unregister(&ep->dev);
+	class_device_unregister(&ep->dev);
 	return NULL;
 
 free_ep:
@@ -212,32 +203,29 @@ EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
 void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
 {
 	sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
-	device_unregister(&ep->dev);
+	class_device_unregister(&ep->dev);
 }
 EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
 
 struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
 {
-	struct iscsi_endpoint *ep;
-	struct device *dev;
-
-	dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
-				iscsi_match_epid);
-	if (!dev)
-		return NULL;
+	struct iscsi_endpoint *ep = NULL;
+	struct class_device *cdev;
 
-	ep = iscsi_dev_to_endpoint(dev);
-	/*
-	 * we can drop this now because the interface will prevent
-	 * removals and lookups from racing.
-	 */
-	put_device(dev);
+	down_read(&iscsi_endpoint_class.subsys.rwsem);
+	list_for_each_entry(cdev, &iscsi_endpoint_class.children, node) {
+		ep = iscsi_dev_to_endpoint(cdev);
+		if (ep->id == handle)
+			break;
+		ep = NULL;
+	}
+	up_read(&iscsi_endpoint_class.subsys.rwsem);
 	return ep;
 }
 EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
 
 static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
-			    struct device *cdev)
+			    struct class_device *cdev)
 {
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct iscsi_cls_host *ihost = shost->shost_data;
@@ -499,7 +487,7 @@ static void session_recovery_timedout(struct work_struct *work)
 {
 	struct iscsi_cls_session *session =
 		container_of(work, struct iscsi_cls_session,
-			     recovery_work.work);
+			     recovery_work);
 	unsigned long flags;
 
 	iscsi_cls_session_printk(KERN_INFO, session,
@@ -530,8 +518,6 @@ static void __iscsi_unblock_session(struct work_struct *work)
 	struct iscsi_cls_session *session =
 			container_of(work, struct iscsi_cls_session,
 				     unblock_work);
-	struct Scsi_Host *shost = iscsi_session_to_shost(session);
-	struct iscsi_cls_host *ihost = shost->shost_data;
 	unsigned long flags;
 
 	/*
@@ -544,15 +530,6 @@ static void __iscsi_unblock_session(struct work_struct *work)
 	spin_unlock_irqrestore(&session->lock, flags);
 	/* start IO */
 	scsi_target_unblock(&session->dev);
-	/*
-	 * Only do kernel scanning if the driver is properly hooked into
-	 * the async scanning code (drivers like iscsi_tcp do login and
-	 * scanning from userspace).
-	 */
-	if (shost->hostt->scan_finished) {
-		if (scsi_queue_work(shost, &session->scan_work))
-			atomic_inc(&ihost->nr_scans);
-	}
 }
 
 /**
@@ -698,7 +675,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
 	}
 	session->target_id = id;
 
-	dev_set_name(&session->dev, "session%u", session->sid);
+	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", session->sid);
 	err = device_add(&session->dev);
 	if (err) {
 		iscsi_cls_session_printk(KERN_ERR, session,
@@ -870,7 +847,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
 	if (!get_device(&session->dev))
 		goto free_conn;
 
-	dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
+	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
+                 session->sid, cid);
 	conn->dev.parent = &session->dev;
 	conn->dev.release = iscsi_conn_release;
 	err = device_register(&conn->dev);
@@ -940,7 +918,15 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt)
 static int
 iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
 {
-	return nlmsg_multicast(nls, skb, 0, group, gfp);
+	int err;
+
+	NETLINK_CB(skb).dst_group = group;
+	
+	err = netlink_broadcast(nls, skb, 0, group, gfp);
+	if (err > 0)
+		err = 0;
+
+	return err;
 }
 
 int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
@@ -1572,51 +1558,65 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
  * Malformed skbs with wrong lengths or invalid creds are not processed.
  */
 static void
-iscsi_if_rx(struct sk_buff *skb)
+iscsi_if_rx(struct sock *sk, int len)
 {
-	mutex_lock(&rx_queue_mutex);
-	while (skb->len >= NLMSG_SPACE(0)) {
-		int err;
-		uint32_t rlen;
-		struct nlmsghdr	*nlh;
-		struct iscsi_uevent *ev;
-		uint32_t group;
-
-		nlh = nlmsg_hdr(skb);
-		if (nlh->nlmsg_len < sizeof(*nlh) ||
-		    skb->len < nlh->nlmsg_len) {
-			break;
-		}
-
-		ev = NLMSG_DATA(nlh);
-		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
-		if (rlen > skb->len)
-			rlen = skb->len;
+	struct sk_buff *skb;
 
-		err = iscsi_if_recv_msg(skb, nlh, &group);
-		if (err) {
-			ev->type = ISCSI_KEVENT_IF_ERROR;
-			ev->iferror = err;
+	mutex_lock(&rx_queue_mutex);
+	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+		if (NETLINK_CREDS(skb)->uid) {
+			skb_pull(skb, skb->len);
+			goto free_skb;
 		}
-		do {
-			/*
-			 * special case for GET_STATS:
-			 * on success - sending reply and stats from
-			 * inside of if_recv_msg(),
-			 * on error - fall through.
-			 */
-			if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
+	
+		while (skb->len >= NLMSG_SPACE(0)) {
+			int err;
+			uint32_t rlen;
+			struct nlmsghdr *nlh;
+			struct iscsi_uevent *ev;
+			uint32_t group;
+			
+			nlh = nlmsg_hdr(skb);
+			if (nlh->nlmsg_len < sizeof(*nlh) ||
+				skb->len < nlh->nlmsg_len) {
 				break;
-			err = iscsi_if_send_reply(group, nlh->nlmsg_seq,
-				nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
-		} while (err < 0 && err != -ECONNREFUSED);
-		skb_pull(skb, rlen);
+			}
+
+			ev = NLMSG_DATA(nlh);
+			rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+			if (rlen > skb->len)
+				rlen = skb->len;
+
+			err = iscsi_if_recv_msg(skb, nlh, &group);
+			if (err) {
+				ev->type = ISCSI_KEVENT_IF_ERROR;
+				ev->iferror = err;
+			}
+			do {
+				/*
+				 * special case for GET_STATS:
+				 * on success - sending reply and stats from
+				 * inside of if_recv_msg(),
+				 * on error - fall through.
+				 */
+				if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
+					break;
+				err = iscsi_if_send_reply(group, nlh->nlmsg_seq,
+						nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
+			} while (err < 0 && err != -ECONNREFUSED);
+			skb_pull(skb, rlen);
+		}
+free_skb:
+		kfree_skb(skb);
 	}
 	mutex_unlock(&rx_queue_mutex);
 }
 
+#define iscsi_cdev_to_conn(_cdev) \
+	iscsi_dev_to_conn(_cdev->dev)
+
 #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)		\
-struct device_attribute dev_attr_##_prefix##_##_name =	\
+struct class_device_attribute class_device_attr_##_prefix##_##_name =  \
 	__ATTR(_name,_mode,_show,_store)
 
 /*
@@ -1624,10 +1624,9 @@ struct device_attribute dev_attr_##_prefix##_##_name =	\
  */
 #define iscsi_conn_attr_show(param)					\
 static ssize_t								\
-show_conn_param_##param(struct device *dev, 				\
-			struct device_attribute *attr, char *buf)	\
+show_conn_param_##param(struct class_device *cdev, char *buf)		\
 {									\
-	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
+	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
 	struct iscsi_transport *t = conn->transport;			\
 	return t->get_conn_param(conn, param, buf);			\
 }
@@ -1651,16 +1650,18 @@ iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
 iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
 iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
 
+#define iscsi_cdev_to_session(_cdev) \
+	iscsi_dev_to_session(_cdev->dev)
+
 /*
  * iSCSI session attrs
  */
 #define iscsi_session_attr_show(param, perm)				\
 static ssize_t								\
-show_session_param_##param(struct device *dev,				\
-			   struct device_attribute *attr, char *buf)	\
+show_session_param_##param(struct class_device *cdev, char *buf)	\
 {									\
 	struct iscsi_cls_session *session = 				\
-		iscsi_dev_to_session(dev->parent);			\
+		iscsi_cdev_to_session(cdev);				\
 	struct iscsi_transport *t = session->transport;			\
 									\
 	if (perm && !capable(CAP_SYS_ADMIN))				\
@@ -1694,10 +1695,9 @@ iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
 iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0)
 
 static ssize_t
-show_priv_session_state(struct device *dev, struct device_attribute *attr,
-			char *buf)
+show_priv_session_state(struct class_device *cdev, char *buf)
 {
-	struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
+	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);
 	return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
 }
 static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
@@ -1705,11 +1705,9 @@ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
 
 #define iscsi_priv_session_attr_show(field, format)			\
 static ssize_t								\
-show_priv_session_##field(struct device *dev, 				\
-			  struct device_attribute *attr, char *buf)	\
+show_priv_session_##field(struct class_device *cdev, char *buf)		\
 {									\
-	struct iscsi_cls_session *session = 				\
-			iscsi_dev_to_session(dev->parent);		\
+	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);\
 	return sprintf(buf, format"\n", session->field);		\
 }
 
@@ -1724,10 +1722,9 @@ iscsi_priv_session_attr(recovery_tmo, "%d");
  */
 #define iscsi_host_attr_show(param)					\
 static ssize_t								\
-show_host_param_##param(struct device *dev, 				\
-			struct device_attribute *attr, char *buf)	\
+show_host_param_##param(struct class_device *cdev, char *buf)		\
 {									\
-	struct Scsi_Host *shost = transport_class_to_shost(dev);	\
+	struct Scsi_Host *shost = transport_class_to_shost(cdev);	\
 	struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
 	return priv->iscsi_transport->get_host_param(shost, param, buf); \
 }
@@ -1744,7 +1741,7 @@ iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
 
 #define SETUP_PRIV_SESSION_RD_ATTR(field)				\
 do {									\
-	priv->session_attrs[count] = &dev_attr_priv_sess_##field; \
+	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
 	count++;							\
 } while (0)
 
@@ -1752,7 +1749,7 @@ do {									\
 #define SETUP_SESSION_RD_ATTR(field, param_flag)			\
 do {									\
 	if (tt->param_mask & param_flag) {				\
-		priv->session_attrs[count] = &dev_attr_sess_##field; \
+		priv->session_attrs[count] = &class_device_attr_sess_##field; \
 		count++;						\
 	}								\
 } while (0)
@@ -1760,7 +1757,7 @@ do {									\
 #define SETUP_CONN_RD_ATTR(field, param_flag)				\
 do {									\
 	if (tt->param_mask & param_flag) {				\
-		priv->conn_attrs[count] = &dev_attr_conn_##field; \
+		priv->conn_attrs[count] = &class_device_attr_conn_##field; \
 		count++;						\
 	}								\
 } while (0)
@@ -1768,7 +1765,7 @@ do {									\
 #define SETUP_HOST_RD_ATTR(field, param_flag)				\
 do {									\
 	if (tt->host_param_mask & param_flag) {				\
-		priv->host_attrs[count] = &dev_attr_host_##field; \
+		priv->host_attrs[count] = &class_device_attr_host_##field; \
 		count++;						\
 	}								\
 } while (0)
@@ -1859,15 +1856,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
 	priv->t.user_scan = iscsi_user_scan;
 	priv->t.create_work_queue = 1;
 
-	priv->dev.class = &iscsi_transport_class;
-	dev_set_name(&priv->dev, "%s", tt->name);
-	err = device_register(&priv->dev);
+	priv->cdev.class = &iscsi_transport_class;
+	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+	err = class_device_register(&priv->cdev);
 	if (err)
 		goto free_priv;
 
-	err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
+	err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
 	if (err)
-		goto unregister_dev;
+		goto unregister_cdev;
 
 	/* host parameters */
 	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
@@ -1946,8 +1943,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
 	printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
 	return &priv->t;
 
-unregister_dev:
-	device_unregister(&priv->dev);
+unregister_cdev:
+	class_device_unregister(&priv->cdev);
 	return NULL;
 free_priv:
 	kfree(priv);
@@ -1975,8 +1972,8 @@ int iscsi_unregister_transport(struct iscsi_transport *tt)
 	transport_container_unregister(&priv->session_cont);
 	transport_container_unregister(&priv->t.host_attrs);
 
-	sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
-	device_unregister(&priv->dev);
+	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+	class_device_unregister(&priv->cdev);
 	mutex_unlock(&rx_queue_mutex);
 
 	return 0;
@@ -1999,7 +1996,6 @@ static __init int iscsi_transport_init(void)
 	err = class_register(&iscsi_endpoint_class);
 	if (err)
 		goto unregister_transport_class;
-
 	err = transport_class_register(&iscsi_host_class);
 	if (err)
 		goto unregister_endpoint_class;
@@ -2033,8 +2029,10 @@ unregister_conn_class:
 	transport_class_unregister(&iscsi_connection_class);
 unregister_host_class:
 	transport_class_unregister(&iscsi_host_class);
+
 unregister_endpoint_class:
 	class_unregister(&iscsi_endpoint_class);
+
 unregister_transport_class:
 	class_unregister(&iscsi_transport_class);
 	return err;
diff --git a/kernel/scsi_transport_iscsi.h b/kernel/scsi_transport_iscsi.h
index ef4b697..4efa993 100644
--- a/kernel/scsi_transport_iscsi.h
+++ b/kernel/scsi_transport_iscsi.h
@@ -26,6 +26,7 @@
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include "open_iscsi_compat.h"
 #include "iscsi_if.h"
 
 struct scsi_transport_template;
@@ -190,7 +191,11 @@ struct iscsi_cls_session {
 
 	/* recovery fields */
 	int recovery_tmo;
+#if !(defined RHELC1) && !(defined SLEC1)
 	struct delayed_work recovery_work;
+#else 
+	struct work_struct recovery_work;
+#endif
 
 	unsigned int target_id;
 
@@ -219,7 +224,7 @@ extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
 
 struct iscsi_endpoint {
 	void *dd_data;			/* LLD private data */
-	struct device dev;
+	struct class_device dev;
 	uint64_t id;
 };
 
-- 
1.6.0.6

Reply via email to