[ewg] [PATCH] iscsi backport for OFED1.4
Doron Shoham
dorons at voltaire.com
Sun Jun 29 06:34:39 PDT 2008
Hi Vlad,
This is patch will resolve the compilation errors
of sles10 and redhat5
Thanks,
Doron
Signed-off-by: Doron Shoham <dorons at voltaire.com>
---
...1_sync_kernel_code_with_release_2.0-869.2.patch | 646 ++++++++
.../iscsi_02_count_fmr_align_violations.patch | 24 +
...scsi_03_copmat_patch_for_RHEL5_and_SLES10.patch | 151 ++
...1_sync_kernel_code_with_release_2.0-869.2.patch | 646 ++++++++
.../iscsi_02_count_fmr_align_violations.patch | 24 +
...scsi_03_copmat_patch_for_RHEL5_and_SLES10.patch | 151 ++
...1_sync_kernel_code_with_release_2.0-869.2.patch | 646 ++++++++
.../iscsi_02_count_fmr_align_violations.patch | 24 +
...scsi_03_copmat_patch_for_RHEL5_and_SLES10.patch | 151 ++
...1_sync_kernel_code_with_release_2.0-869.2.patch | 646 ++++++++
.../iscsi_02_count_fmr_align_violations.patch | 24 +
...scsi_03_copmat_patch_for_RHEL5_and_SLES10.patch | 151 ++
...1_sync_kernel_code_with_release_2.0-869.2.patch | 646 ++++++++
.../iscsi_02_count_fmr_align_violations.patch | 24 +
...scsi_03_copmat_patch_for_RHEL5_and_SLES10.patch | 151 ++
...1_sync_kernel_code_with_release_2.0-869.2.patch | 646 ++++++++
.../iscsi_02_count_fmr_align_violations.patch | 24 +
...scsi_03_copmat_patch_for_RHEL5_and_SLES10.patch | 151 ++
20 files changed, 4928 insertions(+), 1786 deletions(-)
create mode 100644 kernel_patches/backport/2.6.16_sles10/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10/iscsi_02_count_fmr_align_violations.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10_sp1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10_sp1/iscsi_02_count_fmr_align_violations.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10_sp1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10_sp2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10_sp2/iscsi_02_count_fmr_align_violations.patch
create mode 100644 kernel_patches/backport/2.6.16_sles10_sp2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
create mode 100644 kernel_patches/backport/2.6.18-EL5.1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
create mode 100644 kernel_patches/backport/2.6.18-EL5.1/iscsi_02_count_fmr_align_violations.patch
create mode 100644 kernel_patches/backport/2.6.18-EL5.1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
create mode 100644 kernel_patches/backport/2.6.18-EL5.2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
create mode 100644 kernel_patches/backport/2.6.18-EL5.2/iscsi_02_count_fmr_align_violations.patch
create mode 100644 kernel_patches/backport/2.6.18-EL5.2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
create mode 100644 kernel_patches/backport/2.6.18_FC6/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
create mode 100644 kernel_patches/backport/2.6.18_FC6/iscsi_02_count_fmr_align_violations.patch
create mode 100644 kernel_patches/backport/2.6.18_FC6/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
diff --git a/kernel_patches/backport/2.6.16_sles10/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch b/kernel_patches/backport/2.6.16_sles10/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
new file mode 100644
index 0000000..80375a9
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
@@ -0,0 +1,646 @@
+From d7020ef2830f00c127770c63ad5d3c11cacd6685 Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Thu, 19 Jun 2008 11:33:20 +0300
+Subject: [PATCH 1/1] scsi_01_sync_kernel_code_with_release_2.0-869.2.patch
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/iscsi_tcp.c | 31 ++++----
+ drivers/scsi/libiscsi.c | 140 +++++------------------------------
+ drivers/scsi/scsi_transport_iscsi.c | 107 +++++++++++++--------------
+ include/scsi/libiscsi.h | 1 -
+ 4 files changed, 86 insertions(+), 193 deletions(-)
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a..8a17867 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,7 +528,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -543,10 +542,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, total_in_length);
++ tcp_conn->in.datalen, scsi_bufflen(sc));
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -559,8 +558,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= total_in_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;
+@@ -671,11 +670,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->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(ctask->sc)->length);
++ r2t->data_offset, scsi_bufflen(ctask->sc));
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -772,7 +771,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -790,8 +788,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(ctask->sc),
++ scsi_sg_count(ctask->sc),
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1334,8 +1332,7 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+- scsi_out(sc)->table.nents,
++ err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1389,7 +1386,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
+- struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1416,8 +1412,9 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
++ tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1463,8 +1460,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d..9975095 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,70 +137,6 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
+-/*
+- * make an extended cdb AHS
+- */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *cmd = ctask->sc;
+- unsigned rlen, pad_len;
+- unsigned short ahslength;
+- struct iscsi_ecdb_ahdr *ecdb_ahdr;
+- int rc;
+-
+- ecdb_ahdr = iscsi_next_hdr(ctask);
+- rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+-
+- BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+- ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+-
+- pad_len = iscsi_padding(rlen);
+-
+- rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+- sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+- if (rc)
+- return rc;
+-
+- if (pad_len)
+- memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+-
+- ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+- ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+- ecdb_ahdr->reserved = 0;
+- memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+-
+- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+- cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+-
+- return 0;
+-}
+-
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *sc = ctask->sc;
+- struct iscsi_rlength_ahdr *rlen_ahdr;
+- int rc;
+-
+- rlen_ahdr = iscsi_next_hdr(ctask);
+- rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+- if (rc)
+- return rc;
+-
+- rlen_ahdr->ahslength =
+- cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+- 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);
+-
+- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+- "rlen_ahdr->ahslength(%d)\n",
+- be32_to_cpu(rlen_ahdr->read_length),
+- be16_to_cpu(rlen_ahdr->ahslength));
+- return 0;
+-}
+-
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -214,7 +150,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength, cmd_len;
++ unsigned hdrlength;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -225,30 +161,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- cmd_len = sc->cmd_len;
+- if (cmd_len < ISCSI_CDB_SIZE)
+- memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+- else if (cmd_len > ISCSI_CDB_SIZE) {
+- rc = iscsi_prep_ecdb_ahs(ctask);
+- if (rc)
+- return rc;
+- cmd_len = ISCSI_CDB_SIZE;
+- }
+- memcpy(hdr->cdb, sc->cmnd, cmd_len);
++ memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++ if (sc->cmd_len < MAX_COMMAND_SIZE)
++ memset(&hdr->cdb[sc->cmd_len], 0,
++ MAX_COMMAND_SIZE - sc->cmd_len);
+
+ ctask->imm_count = 0;
+- if (scsi_bidi_cmnd(sc)) {
+- hdr->flags |= ISCSI_FLAG_CMD_READ;
+- rc = iscsi_prep_bidi_ahs(ctask);
+- if (rc)
+- return rc;
+- }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
+- hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -269,19 +192,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (out_len >= session->first_burst)
++ if (scsi_bufflen(sc) >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(out_len,
++ ctask->imm_count = min(scsi_bufflen(sc),
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min(session->first_burst, out_len)
+- - ctask->imm_count;
++ ctask->unsol_count = min((session->first_burst),
++ (scsi_bufflen(sc))) - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -291,7 +214,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -310,12 +232,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+- "len %d bidi_len %d cmdsn %d win %d]\n",
+- scsi_bidi_cmnd(sc) ? "bidirectional" :
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt,
+- scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++ "cmdsn %d win %d]\n",
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -378,12 +298,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- 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));
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -518,18 +433,6 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
+- if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+- int res_count = be32_to_cpu(rhdr->bi_residual_count);
+-
+- 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;
+- else
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
+-
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -537,11 +440,13 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
+- /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
++ } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1199,12 +1104,7 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("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));
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737..ca7bb6f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/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,27 +78,25 @@ 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");
+ show_transport_attr(max_lun, "%d");
+@@ -106,11 +104,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
+- &dev_attr_max_lun.attr,
+- &dev_attr_max_conn.attr,
+- &dev_attr_max_cmd_len.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
++ &class_device_attr_max_lun.attr,
++ &class_device_attr_max_conn.attr,
++ &class_device_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -121,7 +119,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ 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_host *ihost = shost->shost_data;
+@@ -141,7 +139,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_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_host *ihost = shost->shost_data;
+@@ -1339,8 +1337,11 @@ iscsi_if_rx(struct sk_buff *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)
+
+ /*
+@@ -1348,10 +1349,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); \
+ }
+@@ -1375,16 +1375,17 @@ 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); \
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1416,10 +1417,9 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 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,
+@@ -1427,11 +1427,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); \
+ }
+
+@@ -1446,10 +1444,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); \
+ }
+@@ -1466,7 +1463,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)
+
+@@ -1474,7 +1471,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)
+@@ -1482,7 +1479,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)
+@@ -1490,7 +1487,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)
+@@ -1581,15 +1578,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->dev.class = &iscsi_transport_class;
+- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%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];
+@@ -1666,8 +1663,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);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1694,8 +1691,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;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63..7b90b63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,7 +225,6 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
+- uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.16_sles10/iscsi_02_count_fmr_align_violations.patch b/kernel_patches/backport/2.6.16_sles10/iscsi_02_count_fmr_align_violations.patch
new file mode 100644
index 0000000..9bf2d19
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10/iscsi_02_count_fmr_align_violations.patch
@@ -0,0 +1,24 @@
+From 02753dd2caabfe6b1885cb80a8fb8532b416108d Mon Sep 17 00:00:00 2001
+From: Eli Dorfman <elid at voltaire.com>
+Date: Tue, 29 Apr 2008 10:12:39 +0300
+Subject: [PATCH] IB/iSER: Count fmr alignment violations per session
+
+Count fmr alignment violations per session
+as part of the iscsi statistics.
+
+Signed-off-by: Eli Dorfman <elid at voltaire.com>
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.5
+
diff --git a/kernel_patches/backport/2.6.16_sles10/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch b/kernel_patches/backport/2.6.16_sles10/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
new file mode 100644
index 0000000..798571f
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
@@ -0,0 +1,151 @@
+From 66ab30f8dadef133bd04bbdcb434a7f742821bed Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Sun, 29 Jun 2008 15:41:12 +0300
+Subject: [PATCH] copmat patch for RHEL5 and SLES10
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 93 ++++++++++++++++++++---------------
+ 1 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..0ccd7e2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -20,6 +20,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
++#include <linux/version.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <net/tcp.h>
+@@ -397,10 +399,12 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ * the async scanning code (drivers like iscsi_tcp do login and
+ * scanning from userspace).
+ */
+- if (shost->hostt->scan_finished) {
+- if (queue_work(ihost->scan_workq, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++ if (shost->hostt->scan_finished) {
++ if (queue_work(ihost->scan_workq, &session->scan_work))
++ atomic_inc(&ihost->nr_scans);
++ }
++#endif
+ }
+
+ /**
+@@ -1294,45 +1298,56 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ * 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)
+ {
++ struct sk_buff *skb;
++
+ mutex_lock(&rx_queue_mutex);
+- while (skb->len >= NLMSG_SPACE(0)) {
+- int err;
+- uint32_t rlen;
+- struct nlmsghdr *nlh;
+- struct iscsi_uevent *ev;
+-
+- nlh = nlmsg_hdr(skb);
+- if (nlh->nlmsg_len < sizeof(*nlh) ||
+- skb->len < nlh->nlmsg_len) {
+- break;
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (NETLINK_CREDS(skb)->uid) {
++ skb_pull(skb, skb->len);
++ goto free_skb;
+ }
+
+- ev = NLMSG_DATA(nlh);
+- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+- if (rlen > skb->len)
+- rlen = skb->len;
++ while (skb->len >= NLMSG_SPACE(0)) {
++ int err;
++ uint32_t rlen;
++ struct nlmsghdr *nlh;
++ struct iscsi_uevent *ev;
+
+- err = iscsi_if_recv_msg(skb, nlh);
+- 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)
++ nlh = nlmsg_hdr(skb);
++ if (nlh->nlmsg_len < sizeof(*nlh) ||
++ skb->len < nlh->nlmsg_len) {
+ break;
+- err = iscsi_if_send_reply(
+- NETLINK_CREDS(skb)->pid, 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);
++ 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(
++ NETLINK_CREDS(skb)->pid, 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);
+ }
+@@ -1738,7 +1753,7 @@ static __init int iscsi_transport_init(void)
+ return 0;
+
+ release_nls:
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ unregister_session_class:
+ transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1753,7 +1768,7 @@ unregister_transport_class:
+ static void __exit iscsi_transport_exit(void)
+ {
+ destroy_workqueue(iscsi_eh_timer_workq);
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
new file mode 100644
index 0000000..80375a9
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
@@ -0,0 +1,646 @@
+From d7020ef2830f00c127770c63ad5d3c11cacd6685 Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Thu, 19 Jun 2008 11:33:20 +0300
+Subject: [PATCH 1/1] scsi_01_sync_kernel_code_with_release_2.0-869.2.patch
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/iscsi_tcp.c | 31 ++++----
+ drivers/scsi/libiscsi.c | 140 +++++------------------------------
+ drivers/scsi/scsi_transport_iscsi.c | 107 +++++++++++++--------------
+ include/scsi/libiscsi.h | 1 -
+ 4 files changed, 86 insertions(+), 193 deletions(-)
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a..8a17867 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,7 +528,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -543,10 +542,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, total_in_length);
++ tcp_conn->in.datalen, scsi_bufflen(sc));
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -559,8 +558,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= total_in_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;
+@@ -671,11 +670,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->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(ctask->sc)->length);
++ r2t->data_offset, scsi_bufflen(ctask->sc));
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -772,7 +771,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -790,8 +788,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(ctask->sc),
++ scsi_sg_count(ctask->sc),
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1334,8 +1332,7 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+- scsi_out(sc)->table.nents,
++ err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1389,7 +1386,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
+- struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1416,8 +1412,9 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
++ tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1463,8 +1460,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d..9975095 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,70 +137,6 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
+-/*
+- * make an extended cdb AHS
+- */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *cmd = ctask->sc;
+- unsigned rlen, pad_len;
+- unsigned short ahslength;
+- struct iscsi_ecdb_ahdr *ecdb_ahdr;
+- int rc;
+-
+- ecdb_ahdr = iscsi_next_hdr(ctask);
+- rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+-
+- BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+- ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+-
+- pad_len = iscsi_padding(rlen);
+-
+- rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+- sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+- if (rc)
+- return rc;
+-
+- if (pad_len)
+- memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+-
+- ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+- ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+- ecdb_ahdr->reserved = 0;
+- memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+-
+- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+- cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+-
+- return 0;
+-}
+-
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *sc = ctask->sc;
+- struct iscsi_rlength_ahdr *rlen_ahdr;
+- int rc;
+-
+- rlen_ahdr = iscsi_next_hdr(ctask);
+- rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+- if (rc)
+- return rc;
+-
+- rlen_ahdr->ahslength =
+- cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+- 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);
+-
+- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+- "rlen_ahdr->ahslength(%d)\n",
+- be32_to_cpu(rlen_ahdr->read_length),
+- be16_to_cpu(rlen_ahdr->ahslength));
+- return 0;
+-}
+-
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -214,7 +150,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength, cmd_len;
++ unsigned hdrlength;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -225,30 +161,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- cmd_len = sc->cmd_len;
+- if (cmd_len < ISCSI_CDB_SIZE)
+- memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+- else if (cmd_len > ISCSI_CDB_SIZE) {
+- rc = iscsi_prep_ecdb_ahs(ctask);
+- if (rc)
+- return rc;
+- cmd_len = ISCSI_CDB_SIZE;
+- }
+- memcpy(hdr->cdb, sc->cmnd, cmd_len);
++ memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++ if (sc->cmd_len < MAX_COMMAND_SIZE)
++ memset(&hdr->cdb[sc->cmd_len], 0,
++ MAX_COMMAND_SIZE - sc->cmd_len);
+
+ ctask->imm_count = 0;
+- if (scsi_bidi_cmnd(sc)) {
+- hdr->flags |= ISCSI_FLAG_CMD_READ;
+- rc = iscsi_prep_bidi_ahs(ctask);
+- if (rc)
+- return rc;
+- }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
+- hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -269,19 +192,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (out_len >= session->first_burst)
++ if (scsi_bufflen(sc) >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(out_len,
++ ctask->imm_count = min(scsi_bufflen(sc),
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min(session->first_burst, out_len)
+- - ctask->imm_count;
++ ctask->unsol_count = min((session->first_burst),
++ (scsi_bufflen(sc))) - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -291,7 +214,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -310,12 +232,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+- "len %d bidi_len %d cmdsn %d win %d]\n",
+- scsi_bidi_cmnd(sc) ? "bidirectional" :
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt,
+- scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++ "cmdsn %d win %d]\n",
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -378,12 +298,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- 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));
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -518,18 +433,6 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
+- if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+- int res_count = be32_to_cpu(rhdr->bi_residual_count);
+-
+- 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;
+- else
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
+-
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -537,11 +440,13 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
+- /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
++ } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1199,12 +1104,7 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("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));
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737..ca7bb6f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/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,27 +78,25 @@ 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");
+ show_transport_attr(max_lun, "%d");
+@@ -106,11 +104,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
+- &dev_attr_max_lun.attr,
+- &dev_attr_max_conn.attr,
+- &dev_attr_max_cmd_len.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
++ &class_device_attr_max_lun.attr,
++ &class_device_attr_max_conn.attr,
++ &class_device_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -121,7 +119,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ 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_host *ihost = shost->shost_data;
+@@ -141,7 +139,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_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_host *ihost = shost->shost_data;
+@@ -1339,8 +1337,11 @@ iscsi_if_rx(struct sk_buff *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)
+
+ /*
+@@ -1348,10 +1349,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); \
+ }
+@@ -1375,16 +1375,17 @@ 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); \
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1416,10 +1417,9 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 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,
+@@ -1427,11 +1427,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); \
+ }
+
+@@ -1446,10 +1444,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); \
+ }
+@@ -1466,7 +1463,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)
+
+@@ -1474,7 +1471,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)
+@@ -1482,7 +1479,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)
+@@ -1490,7 +1487,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)
+@@ -1581,15 +1578,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->dev.class = &iscsi_transport_class;
+- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%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];
+@@ -1666,8 +1663,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);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1694,8 +1691,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;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63..7b90b63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,7 +225,6 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
+- uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_02_count_fmr_align_violations.patch b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_02_count_fmr_align_violations.patch
new file mode 100644
index 0000000..9bf2d19
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_02_count_fmr_align_violations.patch
@@ -0,0 +1,24 @@
+From 02753dd2caabfe6b1885cb80a8fb8532b416108d Mon Sep 17 00:00:00 2001
+From: Eli Dorfman <elid at voltaire.com>
+Date: Tue, 29 Apr 2008 10:12:39 +0300
+Subject: [PATCH] IB/iSER: Count fmr alignment violations per session
+
+Count fmr alignment violations per session
+as part of the iscsi statistics.
+
+Signed-off-by: Eli Dorfman <elid at voltaire.com>
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.5
+
diff --git a/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
new file mode 100644
index 0000000..798571f
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
@@ -0,0 +1,151 @@
+From 66ab30f8dadef133bd04bbdcb434a7f742821bed Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Sun, 29 Jun 2008 15:41:12 +0300
+Subject: [PATCH] copmat patch for RHEL5 and SLES10
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 93 ++++++++++++++++++++---------------
+ 1 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..0ccd7e2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -20,6 +20,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
++#include <linux/version.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <net/tcp.h>
+@@ -397,10 +399,12 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ * the async scanning code (drivers like iscsi_tcp do login and
+ * scanning from userspace).
+ */
+- if (shost->hostt->scan_finished) {
+- if (queue_work(ihost->scan_workq, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++ if (shost->hostt->scan_finished) {
++ if (queue_work(ihost->scan_workq, &session->scan_work))
++ atomic_inc(&ihost->nr_scans);
++ }
++#endif
+ }
+
+ /**
+@@ -1294,45 +1298,56 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ * 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)
+ {
++ struct sk_buff *skb;
++
+ mutex_lock(&rx_queue_mutex);
+- while (skb->len >= NLMSG_SPACE(0)) {
+- int err;
+- uint32_t rlen;
+- struct nlmsghdr *nlh;
+- struct iscsi_uevent *ev;
+-
+- nlh = nlmsg_hdr(skb);
+- if (nlh->nlmsg_len < sizeof(*nlh) ||
+- skb->len < nlh->nlmsg_len) {
+- break;
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (NETLINK_CREDS(skb)->uid) {
++ skb_pull(skb, skb->len);
++ goto free_skb;
+ }
+
+- ev = NLMSG_DATA(nlh);
+- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+- if (rlen > skb->len)
+- rlen = skb->len;
++ while (skb->len >= NLMSG_SPACE(0)) {
++ int err;
++ uint32_t rlen;
++ struct nlmsghdr *nlh;
++ struct iscsi_uevent *ev;
+
+- err = iscsi_if_recv_msg(skb, nlh);
+- 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)
++ nlh = nlmsg_hdr(skb);
++ if (nlh->nlmsg_len < sizeof(*nlh) ||
++ skb->len < nlh->nlmsg_len) {
+ break;
+- err = iscsi_if_send_reply(
+- NETLINK_CREDS(skb)->pid, 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);
++ 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(
++ NETLINK_CREDS(skb)->pid, 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);
+ }
+@@ -1738,7 +1753,7 @@ static __init int iscsi_transport_init(void)
+ return 0;
+
+ release_nls:
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ unregister_session_class:
+ transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1753,7 +1768,7 @@ unregister_transport_class:
+ static void __exit iscsi_transport_exit(void)
+ {
+ destroy_workqueue(iscsi_eh_timer_workq);
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch b/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
new file mode 100644
index 0000000..80375a9
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
@@ -0,0 +1,646 @@
+From d7020ef2830f00c127770c63ad5d3c11cacd6685 Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Thu, 19 Jun 2008 11:33:20 +0300
+Subject: [PATCH 1/1] scsi_01_sync_kernel_code_with_release_2.0-869.2.patch
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/iscsi_tcp.c | 31 ++++----
+ drivers/scsi/libiscsi.c | 140 +++++------------------------------
+ drivers/scsi/scsi_transport_iscsi.c | 107 +++++++++++++--------------
+ include/scsi/libiscsi.h | 1 -
+ 4 files changed, 86 insertions(+), 193 deletions(-)
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a..8a17867 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,7 +528,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -543,10 +542,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, total_in_length);
++ tcp_conn->in.datalen, scsi_bufflen(sc));
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -559,8 +558,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= total_in_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;
+@@ -671,11 +670,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->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(ctask->sc)->length);
++ r2t->data_offset, scsi_bufflen(ctask->sc));
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -772,7 +771,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -790,8 +788,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(ctask->sc),
++ scsi_sg_count(ctask->sc),
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1334,8 +1332,7 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+- scsi_out(sc)->table.nents,
++ err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1389,7 +1386,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
+- struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1416,8 +1412,9 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
++ tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1463,8 +1460,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d..9975095 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,70 +137,6 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
+-/*
+- * make an extended cdb AHS
+- */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *cmd = ctask->sc;
+- unsigned rlen, pad_len;
+- unsigned short ahslength;
+- struct iscsi_ecdb_ahdr *ecdb_ahdr;
+- int rc;
+-
+- ecdb_ahdr = iscsi_next_hdr(ctask);
+- rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+-
+- BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+- ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+-
+- pad_len = iscsi_padding(rlen);
+-
+- rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+- sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+- if (rc)
+- return rc;
+-
+- if (pad_len)
+- memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+-
+- ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+- ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+- ecdb_ahdr->reserved = 0;
+- memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+-
+- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+- cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+-
+- return 0;
+-}
+-
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *sc = ctask->sc;
+- struct iscsi_rlength_ahdr *rlen_ahdr;
+- int rc;
+-
+- rlen_ahdr = iscsi_next_hdr(ctask);
+- rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+- if (rc)
+- return rc;
+-
+- rlen_ahdr->ahslength =
+- cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+- 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);
+-
+- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+- "rlen_ahdr->ahslength(%d)\n",
+- be32_to_cpu(rlen_ahdr->read_length),
+- be16_to_cpu(rlen_ahdr->ahslength));
+- return 0;
+-}
+-
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -214,7 +150,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength, cmd_len;
++ unsigned hdrlength;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -225,30 +161,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- cmd_len = sc->cmd_len;
+- if (cmd_len < ISCSI_CDB_SIZE)
+- memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+- else if (cmd_len > ISCSI_CDB_SIZE) {
+- rc = iscsi_prep_ecdb_ahs(ctask);
+- if (rc)
+- return rc;
+- cmd_len = ISCSI_CDB_SIZE;
+- }
+- memcpy(hdr->cdb, sc->cmnd, cmd_len);
++ memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++ if (sc->cmd_len < MAX_COMMAND_SIZE)
++ memset(&hdr->cdb[sc->cmd_len], 0,
++ MAX_COMMAND_SIZE - sc->cmd_len);
+
+ ctask->imm_count = 0;
+- if (scsi_bidi_cmnd(sc)) {
+- hdr->flags |= ISCSI_FLAG_CMD_READ;
+- rc = iscsi_prep_bidi_ahs(ctask);
+- if (rc)
+- return rc;
+- }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
+- hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -269,19 +192,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (out_len >= session->first_burst)
++ if (scsi_bufflen(sc) >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(out_len,
++ ctask->imm_count = min(scsi_bufflen(sc),
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min(session->first_burst, out_len)
+- - ctask->imm_count;
++ ctask->unsol_count = min((session->first_burst),
++ (scsi_bufflen(sc))) - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -291,7 +214,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -310,12 +232,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+- "len %d bidi_len %d cmdsn %d win %d]\n",
+- scsi_bidi_cmnd(sc) ? "bidirectional" :
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt,
+- scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++ "cmdsn %d win %d]\n",
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -378,12 +298,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- 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));
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -518,18 +433,6 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
+- if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+- int res_count = be32_to_cpu(rhdr->bi_residual_count);
+-
+- 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;
+- else
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
+-
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -537,11 +440,13 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
+- /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
++ } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1199,12 +1104,7 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("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));
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737..ca7bb6f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/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,27 +78,25 @@ 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");
+ show_transport_attr(max_lun, "%d");
+@@ -106,11 +104,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
+- &dev_attr_max_lun.attr,
+- &dev_attr_max_conn.attr,
+- &dev_attr_max_cmd_len.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
++ &class_device_attr_max_lun.attr,
++ &class_device_attr_max_conn.attr,
++ &class_device_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -121,7 +119,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ 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_host *ihost = shost->shost_data;
+@@ -141,7 +139,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_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_host *ihost = shost->shost_data;
+@@ -1339,8 +1337,11 @@ iscsi_if_rx(struct sk_buff *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)
+
+ /*
+@@ -1348,10 +1349,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); \
+ }
+@@ -1375,16 +1375,17 @@ 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); \
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1416,10 +1417,9 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 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,
+@@ -1427,11 +1427,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); \
+ }
+
+@@ -1446,10 +1444,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); \
+ }
+@@ -1466,7 +1463,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)
+
+@@ -1474,7 +1471,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)
+@@ -1482,7 +1479,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)
+@@ -1490,7 +1487,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)
+@@ -1581,15 +1578,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->dev.class = &iscsi_transport_class;
+- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%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];
+@@ -1666,8 +1663,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);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1694,8 +1691,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;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63..7b90b63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,7 +225,6 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
+- uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_02_count_fmr_align_violations.patch b/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_02_count_fmr_align_violations.patch
new file mode 100644
index 0000000..9bf2d19
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_02_count_fmr_align_violations.patch
@@ -0,0 +1,24 @@
+From 02753dd2caabfe6b1885cb80a8fb8532b416108d Mon Sep 17 00:00:00 2001
+From: Eli Dorfman <elid at voltaire.com>
+Date: Tue, 29 Apr 2008 10:12:39 +0300
+Subject: [PATCH] IB/iSER: Count fmr alignment violations per session
+
+Count fmr alignment violations per session
+as part of the iscsi statistics.
+
+Signed-off-by: Eli Dorfman <elid at voltaire.com>
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.5
+
diff --git a/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch b/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
new file mode 100644
index 0000000..798571f
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
@@ -0,0 +1,151 @@
+From 66ab30f8dadef133bd04bbdcb434a7f742821bed Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Sun, 29 Jun 2008 15:41:12 +0300
+Subject: [PATCH] copmat patch for RHEL5 and SLES10
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 93 ++++++++++++++++++++---------------
+ 1 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..0ccd7e2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -20,6 +20,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
++#include <linux/version.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <net/tcp.h>
+@@ -397,10 +399,12 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ * the async scanning code (drivers like iscsi_tcp do login and
+ * scanning from userspace).
+ */
+- if (shost->hostt->scan_finished) {
+- if (queue_work(ihost->scan_workq, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++ if (shost->hostt->scan_finished) {
++ if (queue_work(ihost->scan_workq, &session->scan_work))
++ atomic_inc(&ihost->nr_scans);
++ }
++#endif
+ }
+
+ /**
+@@ -1294,45 +1298,56 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ * 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)
+ {
++ struct sk_buff *skb;
++
+ mutex_lock(&rx_queue_mutex);
+- while (skb->len >= NLMSG_SPACE(0)) {
+- int err;
+- uint32_t rlen;
+- struct nlmsghdr *nlh;
+- struct iscsi_uevent *ev;
+-
+- nlh = nlmsg_hdr(skb);
+- if (nlh->nlmsg_len < sizeof(*nlh) ||
+- skb->len < nlh->nlmsg_len) {
+- break;
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (NETLINK_CREDS(skb)->uid) {
++ skb_pull(skb, skb->len);
++ goto free_skb;
+ }
+
+- ev = NLMSG_DATA(nlh);
+- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+- if (rlen > skb->len)
+- rlen = skb->len;
++ while (skb->len >= NLMSG_SPACE(0)) {
++ int err;
++ uint32_t rlen;
++ struct nlmsghdr *nlh;
++ struct iscsi_uevent *ev;
+
+- err = iscsi_if_recv_msg(skb, nlh);
+- 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)
++ nlh = nlmsg_hdr(skb);
++ if (nlh->nlmsg_len < sizeof(*nlh) ||
++ skb->len < nlh->nlmsg_len) {
+ break;
+- err = iscsi_if_send_reply(
+- NETLINK_CREDS(skb)->pid, 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);
++ 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(
++ NETLINK_CREDS(skb)->pid, 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);
+ }
+@@ -1738,7 +1753,7 @@ static __init int iscsi_transport_init(void)
+ return 0;
+
+ release_nls:
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ unregister_session_class:
+ transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1753,7 +1768,7 @@ unregister_transport_class:
+ static void __exit iscsi_transport_exit(void)
+ {
+ destroy_workqueue(iscsi_eh_timer_workq);
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.18-EL5.1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch b/kernel_patches/backport/2.6.18-EL5.1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
new file mode 100644
index 0000000..80375a9
--- /dev/null
+++ b/kernel_patches/backport/2.6.18-EL5.1/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
@@ -0,0 +1,646 @@
+From d7020ef2830f00c127770c63ad5d3c11cacd6685 Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Thu, 19 Jun 2008 11:33:20 +0300
+Subject: [PATCH 1/1] scsi_01_sync_kernel_code_with_release_2.0-869.2.patch
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/iscsi_tcp.c | 31 ++++----
+ drivers/scsi/libiscsi.c | 140 +++++------------------------------
+ drivers/scsi/scsi_transport_iscsi.c | 107 +++++++++++++--------------
+ include/scsi/libiscsi.h | 1 -
+ 4 files changed, 86 insertions(+), 193 deletions(-)
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a..8a17867 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,7 +528,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -543,10 +542,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, total_in_length);
++ tcp_conn->in.datalen, scsi_bufflen(sc));
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -559,8 +558,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= total_in_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;
+@@ -671,11 +670,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->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(ctask->sc)->length);
++ r2t->data_offset, scsi_bufflen(ctask->sc));
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -772,7 +771,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -790,8 +788,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(ctask->sc),
++ scsi_sg_count(ctask->sc),
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1334,8 +1332,7 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+- scsi_out(sc)->table.nents,
++ err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1389,7 +1386,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
+- struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1416,8 +1412,9 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
++ tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1463,8 +1460,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d..9975095 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,70 +137,6 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
+-/*
+- * make an extended cdb AHS
+- */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *cmd = ctask->sc;
+- unsigned rlen, pad_len;
+- unsigned short ahslength;
+- struct iscsi_ecdb_ahdr *ecdb_ahdr;
+- int rc;
+-
+- ecdb_ahdr = iscsi_next_hdr(ctask);
+- rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+-
+- BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+- ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+-
+- pad_len = iscsi_padding(rlen);
+-
+- rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+- sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+- if (rc)
+- return rc;
+-
+- if (pad_len)
+- memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+-
+- ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+- ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+- ecdb_ahdr->reserved = 0;
+- memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+-
+- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+- cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+-
+- return 0;
+-}
+-
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *sc = ctask->sc;
+- struct iscsi_rlength_ahdr *rlen_ahdr;
+- int rc;
+-
+- rlen_ahdr = iscsi_next_hdr(ctask);
+- rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+- if (rc)
+- return rc;
+-
+- rlen_ahdr->ahslength =
+- cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+- 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);
+-
+- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+- "rlen_ahdr->ahslength(%d)\n",
+- be32_to_cpu(rlen_ahdr->read_length),
+- be16_to_cpu(rlen_ahdr->ahslength));
+- return 0;
+-}
+-
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -214,7 +150,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength, cmd_len;
++ unsigned hdrlength;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -225,30 +161,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- cmd_len = sc->cmd_len;
+- if (cmd_len < ISCSI_CDB_SIZE)
+- memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+- else if (cmd_len > ISCSI_CDB_SIZE) {
+- rc = iscsi_prep_ecdb_ahs(ctask);
+- if (rc)
+- return rc;
+- cmd_len = ISCSI_CDB_SIZE;
+- }
+- memcpy(hdr->cdb, sc->cmnd, cmd_len);
++ memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++ if (sc->cmd_len < MAX_COMMAND_SIZE)
++ memset(&hdr->cdb[sc->cmd_len], 0,
++ MAX_COMMAND_SIZE - sc->cmd_len);
+
+ ctask->imm_count = 0;
+- if (scsi_bidi_cmnd(sc)) {
+- hdr->flags |= ISCSI_FLAG_CMD_READ;
+- rc = iscsi_prep_bidi_ahs(ctask);
+- if (rc)
+- return rc;
+- }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
+- hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -269,19 +192,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (out_len >= session->first_burst)
++ if (scsi_bufflen(sc) >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(out_len,
++ ctask->imm_count = min(scsi_bufflen(sc),
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min(session->first_burst, out_len)
+- - ctask->imm_count;
++ ctask->unsol_count = min((session->first_burst),
++ (scsi_bufflen(sc))) - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -291,7 +214,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -310,12 +232,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+- "len %d bidi_len %d cmdsn %d win %d]\n",
+- scsi_bidi_cmnd(sc) ? "bidirectional" :
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt,
+- scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++ "cmdsn %d win %d]\n",
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -378,12 +298,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- 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));
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -518,18 +433,6 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
+- if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+- int res_count = be32_to_cpu(rhdr->bi_residual_count);
+-
+- 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;
+- else
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
+-
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -537,11 +440,13 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
+- /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
++ } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1199,12 +1104,7 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("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));
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737..ca7bb6f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/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,27 +78,25 @@ 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");
+ show_transport_attr(max_lun, "%d");
+@@ -106,11 +104,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
+- &dev_attr_max_lun.attr,
+- &dev_attr_max_conn.attr,
+- &dev_attr_max_cmd_len.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
++ &class_device_attr_max_lun.attr,
++ &class_device_attr_max_conn.attr,
++ &class_device_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -121,7 +119,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ 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_host *ihost = shost->shost_data;
+@@ -141,7 +139,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_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_host *ihost = shost->shost_data;
+@@ -1339,8 +1337,11 @@ iscsi_if_rx(struct sk_buff *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)
+
+ /*
+@@ -1348,10 +1349,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); \
+ }
+@@ -1375,16 +1375,17 @@ 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); \
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1416,10 +1417,9 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 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,
+@@ -1427,11 +1427,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); \
+ }
+
+@@ -1446,10 +1444,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); \
+ }
+@@ -1466,7 +1463,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)
+
+@@ -1474,7 +1471,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)
+@@ -1482,7 +1479,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)
+@@ -1490,7 +1487,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)
+@@ -1581,15 +1578,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->dev.class = &iscsi_transport_class;
+- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%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];
+@@ -1666,8 +1663,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);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1694,8 +1691,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;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63..7b90b63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,7 +225,6 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
+- uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.18-EL5.1/iscsi_02_count_fmr_align_violations.patch b/kernel_patches/backport/2.6.18-EL5.1/iscsi_02_count_fmr_align_violations.patch
new file mode 100644
index 0000000..9bf2d19
--- /dev/null
+++ b/kernel_patches/backport/2.6.18-EL5.1/iscsi_02_count_fmr_align_violations.patch
@@ -0,0 +1,24 @@
+From 02753dd2caabfe6b1885cb80a8fb8532b416108d Mon Sep 17 00:00:00 2001
+From: Eli Dorfman <elid at voltaire.com>
+Date: Tue, 29 Apr 2008 10:12:39 +0300
+Subject: [PATCH] IB/iSER: Count fmr alignment violations per session
+
+Count fmr alignment violations per session
+as part of the iscsi statistics.
+
+Signed-off-by: Eli Dorfman <elid at voltaire.com>
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.5
+
diff --git a/kernel_patches/backport/2.6.18-EL5.1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch b/kernel_patches/backport/2.6.18-EL5.1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
new file mode 100644
index 0000000..798571f
--- /dev/null
+++ b/kernel_patches/backport/2.6.18-EL5.1/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
@@ -0,0 +1,151 @@
+From 66ab30f8dadef133bd04bbdcb434a7f742821bed Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Sun, 29 Jun 2008 15:41:12 +0300
+Subject: [PATCH] copmat patch for RHEL5 and SLES10
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 93 ++++++++++++++++++++---------------
+ 1 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..0ccd7e2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -20,6 +20,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
++#include <linux/version.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <net/tcp.h>
+@@ -397,10 +399,12 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ * the async scanning code (drivers like iscsi_tcp do login and
+ * scanning from userspace).
+ */
+- if (shost->hostt->scan_finished) {
+- if (queue_work(ihost->scan_workq, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++ if (shost->hostt->scan_finished) {
++ if (queue_work(ihost->scan_workq, &session->scan_work))
++ atomic_inc(&ihost->nr_scans);
++ }
++#endif
+ }
+
+ /**
+@@ -1294,45 +1298,56 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ * 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)
+ {
++ struct sk_buff *skb;
++
+ mutex_lock(&rx_queue_mutex);
+- while (skb->len >= NLMSG_SPACE(0)) {
+- int err;
+- uint32_t rlen;
+- struct nlmsghdr *nlh;
+- struct iscsi_uevent *ev;
+-
+- nlh = nlmsg_hdr(skb);
+- if (nlh->nlmsg_len < sizeof(*nlh) ||
+- skb->len < nlh->nlmsg_len) {
+- break;
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (NETLINK_CREDS(skb)->uid) {
++ skb_pull(skb, skb->len);
++ goto free_skb;
+ }
+
+- ev = NLMSG_DATA(nlh);
+- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+- if (rlen > skb->len)
+- rlen = skb->len;
++ while (skb->len >= NLMSG_SPACE(0)) {
++ int err;
++ uint32_t rlen;
++ struct nlmsghdr *nlh;
++ struct iscsi_uevent *ev;
+
+- err = iscsi_if_recv_msg(skb, nlh);
+- 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)
++ nlh = nlmsg_hdr(skb);
++ if (nlh->nlmsg_len < sizeof(*nlh) ||
++ skb->len < nlh->nlmsg_len) {
+ break;
+- err = iscsi_if_send_reply(
+- NETLINK_CREDS(skb)->pid, 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);
++ 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(
++ NETLINK_CREDS(skb)->pid, 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);
+ }
+@@ -1738,7 +1753,7 @@ static __init int iscsi_transport_init(void)
+ return 0;
+
+ release_nls:
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ unregister_session_class:
+ transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1753,7 +1768,7 @@ unregister_transport_class:
+ static void __exit iscsi_transport_exit(void)
+ {
+ destroy_workqueue(iscsi_eh_timer_workq);
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.18-EL5.2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch b/kernel_patches/backport/2.6.18-EL5.2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
new file mode 100644
index 0000000..80375a9
--- /dev/null
+++ b/kernel_patches/backport/2.6.18-EL5.2/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
@@ -0,0 +1,646 @@
+From d7020ef2830f00c127770c63ad5d3c11cacd6685 Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Thu, 19 Jun 2008 11:33:20 +0300
+Subject: [PATCH 1/1] scsi_01_sync_kernel_code_with_release_2.0-869.2.patch
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/iscsi_tcp.c | 31 ++++----
+ drivers/scsi/libiscsi.c | 140 +++++------------------------------
+ drivers/scsi/scsi_transport_iscsi.c | 107 +++++++++++++--------------
+ include/scsi/libiscsi.h | 1 -
+ 4 files changed, 86 insertions(+), 193 deletions(-)
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a..8a17867 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,7 +528,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -543,10 +542,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, total_in_length);
++ tcp_conn->in.datalen, scsi_bufflen(sc));
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -559,8 +558,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= total_in_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;
+@@ -671,11 +670,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->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(ctask->sc)->length);
++ r2t->data_offset, scsi_bufflen(ctask->sc));
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -772,7 +771,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -790,8 +788,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(ctask->sc),
++ scsi_sg_count(ctask->sc),
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1334,8 +1332,7 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+- scsi_out(sc)->table.nents,
++ err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1389,7 +1386,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
+- struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1416,8 +1412,9 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
++ tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1463,8 +1460,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d..9975095 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,70 +137,6 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
+-/*
+- * make an extended cdb AHS
+- */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *cmd = ctask->sc;
+- unsigned rlen, pad_len;
+- unsigned short ahslength;
+- struct iscsi_ecdb_ahdr *ecdb_ahdr;
+- int rc;
+-
+- ecdb_ahdr = iscsi_next_hdr(ctask);
+- rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+-
+- BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+- ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+-
+- pad_len = iscsi_padding(rlen);
+-
+- rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+- sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+- if (rc)
+- return rc;
+-
+- if (pad_len)
+- memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+-
+- ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+- ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+- ecdb_ahdr->reserved = 0;
+- memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+-
+- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+- cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+-
+- return 0;
+-}
+-
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *sc = ctask->sc;
+- struct iscsi_rlength_ahdr *rlen_ahdr;
+- int rc;
+-
+- rlen_ahdr = iscsi_next_hdr(ctask);
+- rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+- if (rc)
+- return rc;
+-
+- rlen_ahdr->ahslength =
+- cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+- 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);
+-
+- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+- "rlen_ahdr->ahslength(%d)\n",
+- be32_to_cpu(rlen_ahdr->read_length),
+- be16_to_cpu(rlen_ahdr->ahslength));
+- return 0;
+-}
+-
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -214,7 +150,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength, cmd_len;
++ unsigned hdrlength;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -225,30 +161,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- cmd_len = sc->cmd_len;
+- if (cmd_len < ISCSI_CDB_SIZE)
+- memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+- else if (cmd_len > ISCSI_CDB_SIZE) {
+- rc = iscsi_prep_ecdb_ahs(ctask);
+- if (rc)
+- return rc;
+- cmd_len = ISCSI_CDB_SIZE;
+- }
+- memcpy(hdr->cdb, sc->cmnd, cmd_len);
++ memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++ if (sc->cmd_len < MAX_COMMAND_SIZE)
++ memset(&hdr->cdb[sc->cmd_len], 0,
++ MAX_COMMAND_SIZE - sc->cmd_len);
+
+ ctask->imm_count = 0;
+- if (scsi_bidi_cmnd(sc)) {
+- hdr->flags |= ISCSI_FLAG_CMD_READ;
+- rc = iscsi_prep_bidi_ahs(ctask);
+- if (rc)
+- return rc;
+- }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
+- hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -269,19 +192,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (out_len >= session->first_burst)
++ if (scsi_bufflen(sc) >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(out_len,
++ ctask->imm_count = min(scsi_bufflen(sc),
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min(session->first_burst, out_len)
+- - ctask->imm_count;
++ ctask->unsol_count = min((session->first_burst),
++ (scsi_bufflen(sc))) - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -291,7 +214,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -310,12 +232,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+- "len %d bidi_len %d cmdsn %d win %d]\n",
+- scsi_bidi_cmnd(sc) ? "bidirectional" :
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt,
+- scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++ "cmdsn %d win %d]\n",
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -378,12 +298,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- 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));
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -518,18 +433,6 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
+- if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+- int res_count = be32_to_cpu(rhdr->bi_residual_count);
+-
+- 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;
+- else
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
+-
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -537,11 +440,13 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
+- /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
++ } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1199,12 +1104,7 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("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));
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737..ca7bb6f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/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,27 +78,25 @@ 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");
+ show_transport_attr(max_lun, "%d");
+@@ -106,11 +104,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
+- &dev_attr_max_lun.attr,
+- &dev_attr_max_conn.attr,
+- &dev_attr_max_cmd_len.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
++ &class_device_attr_max_lun.attr,
++ &class_device_attr_max_conn.attr,
++ &class_device_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -121,7 +119,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ 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_host *ihost = shost->shost_data;
+@@ -141,7 +139,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_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_host *ihost = shost->shost_data;
+@@ -1339,8 +1337,11 @@ iscsi_if_rx(struct sk_buff *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)
+
+ /*
+@@ -1348,10 +1349,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); \
+ }
+@@ -1375,16 +1375,17 @@ 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); \
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1416,10 +1417,9 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 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,
+@@ -1427,11 +1427,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); \
+ }
+
+@@ -1446,10 +1444,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); \
+ }
+@@ -1466,7 +1463,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)
+
+@@ -1474,7 +1471,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)
+@@ -1482,7 +1479,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)
+@@ -1490,7 +1487,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)
+@@ -1581,15 +1578,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->dev.class = &iscsi_transport_class;
+- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%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];
+@@ -1666,8 +1663,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);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1694,8 +1691,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;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63..7b90b63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,7 +225,6 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
+- uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.18-EL5.2/iscsi_02_count_fmr_align_violations.patch b/kernel_patches/backport/2.6.18-EL5.2/iscsi_02_count_fmr_align_violations.patch
new file mode 100644
index 0000000..9bf2d19
--- /dev/null
+++ b/kernel_patches/backport/2.6.18-EL5.2/iscsi_02_count_fmr_align_violations.patch
@@ -0,0 +1,24 @@
+From 02753dd2caabfe6b1885cb80a8fb8532b416108d Mon Sep 17 00:00:00 2001
+From: Eli Dorfman <elid at voltaire.com>
+Date: Tue, 29 Apr 2008 10:12:39 +0300
+Subject: [PATCH] IB/iSER: Count fmr alignment violations per session
+
+Count fmr alignment violations per session
+as part of the iscsi statistics.
+
+Signed-off-by: Eli Dorfman <elid at voltaire.com>
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.5
+
diff --git a/kernel_patches/backport/2.6.18-EL5.2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch b/kernel_patches/backport/2.6.18-EL5.2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
new file mode 100644
index 0000000..798571f
--- /dev/null
+++ b/kernel_patches/backport/2.6.18-EL5.2/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
@@ -0,0 +1,151 @@
+From 66ab30f8dadef133bd04bbdcb434a7f742821bed Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Sun, 29 Jun 2008 15:41:12 +0300
+Subject: [PATCH] copmat patch for RHEL5 and SLES10
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 93 ++++++++++++++++++++---------------
+ 1 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..0ccd7e2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -20,6 +20,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
++#include <linux/version.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <net/tcp.h>
+@@ -397,10 +399,12 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ * the async scanning code (drivers like iscsi_tcp do login and
+ * scanning from userspace).
+ */
+- if (shost->hostt->scan_finished) {
+- if (queue_work(ihost->scan_workq, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++ if (shost->hostt->scan_finished) {
++ if (queue_work(ihost->scan_workq, &session->scan_work))
++ atomic_inc(&ihost->nr_scans);
++ }
++#endif
+ }
+
+ /**
+@@ -1294,45 +1298,56 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ * 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)
+ {
++ struct sk_buff *skb;
++
+ mutex_lock(&rx_queue_mutex);
+- while (skb->len >= NLMSG_SPACE(0)) {
+- int err;
+- uint32_t rlen;
+- struct nlmsghdr *nlh;
+- struct iscsi_uevent *ev;
+-
+- nlh = nlmsg_hdr(skb);
+- if (nlh->nlmsg_len < sizeof(*nlh) ||
+- skb->len < nlh->nlmsg_len) {
+- break;
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (NETLINK_CREDS(skb)->uid) {
++ skb_pull(skb, skb->len);
++ goto free_skb;
+ }
+
+- ev = NLMSG_DATA(nlh);
+- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+- if (rlen > skb->len)
+- rlen = skb->len;
++ while (skb->len >= NLMSG_SPACE(0)) {
++ int err;
++ uint32_t rlen;
++ struct nlmsghdr *nlh;
++ struct iscsi_uevent *ev;
+
+- err = iscsi_if_recv_msg(skb, nlh);
+- 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)
++ nlh = nlmsg_hdr(skb);
++ if (nlh->nlmsg_len < sizeof(*nlh) ||
++ skb->len < nlh->nlmsg_len) {
+ break;
+- err = iscsi_if_send_reply(
+- NETLINK_CREDS(skb)->pid, 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);
++ 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(
++ NETLINK_CREDS(skb)->pid, 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);
+ }
+@@ -1738,7 +1753,7 @@ static __init int iscsi_transport_init(void)
+ return 0;
+
+ release_nls:
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ unregister_session_class:
+ transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1753,7 +1768,7 @@ unregister_transport_class:
+ static void __exit iscsi_transport_exit(void)
+ {
+ destroy_workqueue(iscsi_eh_timer_workq);
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.18_FC6/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch b/kernel_patches/backport/2.6.18_FC6/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
new file mode 100644
index 0000000..80375a9
--- /dev/null
+++ b/kernel_patches/backport/2.6.18_FC6/iscsi_01_sync_kernel_code_with_release_2.0-869.2.patch
@@ -0,0 +1,646 @@
+From d7020ef2830f00c127770c63ad5d3c11cacd6685 Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Thu, 19 Jun 2008 11:33:20 +0300
+Subject: [PATCH 1/1] scsi_01_sync_kernel_code_with_release_2.0-869.2.patch
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/iscsi_tcp.c | 31 ++++----
+ drivers/scsi/libiscsi.c | 140 +++++------------------------------
+ drivers/scsi/scsi_transport_iscsi.c | 107 +++++++++++++--------------
+ include/scsi/libiscsi.h | 1 -
+ 4 files changed, 86 insertions(+), 193 deletions(-)
+
+diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
+index 72b9b2a..8a17867 100644
+--- a/drivers/scsi/iscsi_tcp.c
++++ b/drivers/scsi/iscsi_tcp.c
+@@ -528,7 +528,6 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct scsi_cmnd *sc = ctask->sc;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(sc)->length;
+
+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
+ if (tcp_conn->in.datalen == 0)
+@@ -543,10 +542,10 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ tcp_ctask->exp_datasn++;
+
+ tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+- if (tcp_ctask->data_offset + tcp_conn->in.datalen > total_in_length) {
++ if (tcp_ctask->data_offset + tcp_conn->in.datalen > scsi_bufflen(sc)) {
+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
+ __FUNCTION__, tcp_ctask->data_offset,
+- tcp_conn->in.datalen, total_in_length);
++ tcp_conn->in.datalen, scsi_bufflen(sc));
+ return ISCSI_ERR_DATA_OFFSET;
+ }
+
+@@ -559,8 +558,8 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= total_in_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;
+@@ -671,11 +670,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(ctask->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(ctask->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(ctask->sc)->length);
++ r2t->data_offset, scsi_bufflen(ctask->sc));
+ __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -772,7 +771,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(ctask->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -790,8 +788,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen);
+ return iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(ctask->sc),
++ scsi_sg_count(ctask->sc),
+ tcp_ctask->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+@@ -1334,8 +1332,7 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
+ return 0;
+
+ /* If we have immediate data, attach a payload */
+- err = iscsi_tcp_send_data_prep(conn, scsi_out(sc)->table.sgl,
+- scsi_out(sc)->table.nents,
++ err = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc), scsi_sg_count(sc),
+ 0, ctask->imm_count);
+ if (err)
+ return err;
+@@ -1389,7 +1386,6 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct scsi_cmnd *sc = ctask->sc;
+- struct scsi_data_buffer *sdb = scsi_out(sc);
+ int rc = 0;
+
+ flush:
+@@ -1416,8 +1412,9 @@ flush:
+ ctask->itt, tcp_ctask->sent, ctask->data_count);
+
+ iscsi_tcp_send_hdr_prep(conn, hdr, sizeof(*hdr));
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, tcp_ctask->sent,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
++ tcp_ctask->sent,
+ ctask->data_count);
+ if (rc)
+ goto fail;
+@@ -1463,8 +1460,8 @@ flush:
+ iscsi_tcp_send_hdr_prep(conn, &r2t->dtask.hdr,
+ sizeof(struct iscsi_hdr));
+
+- rc = iscsi_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents,
++ rc = iscsi_tcp_send_data_prep(conn, scsi_sglist(sc),
++ scsi_sg_count(sc),
+ r2t->data_offset + r2t->sent,
+ r2t->data_count);
+ if (rc)
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index b43bf1d..9975095 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -137,70 +137,6 @@ static int iscsi_add_hdr(struct iscsi_cmd_task *ctask, unsigned len)
+ return 0;
+ }
+
+-/*
+- * make an extended cdb AHS
+- */
+-static int iscsi_prep_ecdb_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *cmd = ctask->sc;
+- unsigned rlen, pad_len;
+- unsigned short ahslength;
+- struct iscsi_ecdb_ahdr *ecdb_ahdr;
+- int rc;
+-
+- ecdb_ahdr = iscsi_next_hdr(ctask);
+- rlen = cmd->cmd_len - ISCSI_CDB_SIZE;
+-
+- BUG_ON(rlen > sizeof(ecdb_ahdr->ecdb));
+- ahslength = rlen + sizeof(ecdb_ahdr->reserved);
+-
+- pad_len = iscsi_padding(rlen);
+-
+- rc = iscsi_add_hdr(ctask, sizeof(ecdb_ahdr->ahslength) +
+- sizeof(ecdb_ahdr->ahstype) + ahslength + pad_len);
+- if (rc)
+- return rc;
+-
+- if (pad_len)
+- memset(&ecdb_ahdr->ecdb[rlen], 0, pad_len);
+-
+- ecdb_ahdr->ahslength = cpu_to_be16(ahslength);
+- ecdb_ahdr->ahstype = ISCSI_AHSTYPE_CDB;
+- ecdb_ahdr->reserved = 0;
+- memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
+-
+- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
+- cmd->cmd_len, rlen, pad_len, ahslength, ctask->hdr_len);
+-
+- return 0;
+-}
+-
+-static int iscsi_prep_bidi_ahs(struct iscsi_cmd_task *ctask)
+-{
+- struct scsi_cmnd *sc = ctask->sc;
+- struct iscsi_rlength_ahdr *rlen_ahdr;
+- int rc;
+-
+- rlen_ahdr = iscsi_next_hdr(ctask);
+- rc = iscsi_add_hdr(ctask, sizeof(*rlen_ahdr));
+- if (rc)
+- return rc;
+-
+- rlen_ahdr->ahslength =
+- cpu_to_be16(sizeof(rlen_ahdr->read_length) +
+- 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);
+-
+- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
+- "rlen_ahdr->ahslength(%d)\n",
+- be32_to_cpu(rlen_ahdr->read_length),
+- be16_to_cpu(rlen_ahdr->ahslength));
+- return 0;
+-}
+-
+ /**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+@@ -214,7 +150,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ struct iscsi_session *session = conn->session;
+ struct iscsi_cmd *hdr = ctask->hdr;
+ struct scsi_cmnd *sc = ctask->sc;
+- unsigned hdrlength, cmd_len;
++ unsigned hdrlength;
+ int rc;
+
+ ctask->hdr_len = 0;
+@@ -225,30 +161,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ hdr->flags = ISCSI_ATTR_SIMPLE;
+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+ hdr->itt = build_itt(ctask->itt, session->age);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+ hdr->cmdsn = cpu_to_be32(session->cmdsn);
+ session->cmdsn++;
+ hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+- cmd_len = sc->cmd_len;
+- if (cmd_len < ISCSI_CDB_SIZE)
+- memset(&hdr->cdb[cmd_len], 0, ISCSI_CDB_SIZE - cmd_len);
+- else if (cmd_len > ISCSI_CDB_SIZE) {
+- rc = iscsi_prep_ecdb_ahs(ctask);
+- if (rc)
+- return rc;
+- cmd_len = ISCSI_CDB_SIZE;
+- }
+- memcpy(hdr->cdb, sc->cmnd, cmd_len);
++ memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
++ if (sc->cmd_len < MAX_COMMAND_SIZE)
++ memset(&hdr->cdb[sc->cmd_len], 0,
++ MAX_COMMAND_SIZE - sc->cmd_len);
+
+ ctask->imm_count = 0;
+- if (scsi_bidi_cmnd(sc)) {
+- hdr->flags |= ISCSI_FLAG_CMD_READ;
+- rc = iscsi_prep_bidi_ahs(ctask);
+- if (rc)
+- return rc;
+- }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
+- hdr->data_length = cpu_to_be32(out_len);
+ hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+ /*
+ * Write counters:
+@@ -269,19 +192,19 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ ctask->unsol_datasn = 0;
+
+ if (session->imm_data_en) {
+- if (out_len >= session->first_burst)
++ if (scsi_bufflen(sc) >= session->first_burst)
+ ctask->imm_count = min(session->first_burst,
+ conn->max_xmit_dlength);
+ else
+- ctask->imm_count = min(out_len,
++ ctask->imm_count = min(scsi_bufflen(sc),
+ conn->max_xmit_dlength);
+ hton24(hdr->dlength, ctask->imm_count);
+ } else
+ zero_data(hdr->dlength);
+
+ if (!session->initial_r2t_en) {
+- ctask->unsol_count = min(session->first_burst, out_len)
+- - ctask->imm_count;
++ ctask->unsol_count = min((session->first_burst),
++ (scsi_bufflen(sc))) - ctask->imm_count;
+ ctask->unsol_offset = ctask->imm_count;
+ }
+
+@@ -291,7 +214,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -310,12 +232,10 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+ return EIO;
+
+ conn->scsicmd_pdus_cnt++;
+- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x "
+- "len %d bidi_len %d cmdsn %d win %d]\n",
+- scsi_bidi_cmnd(sc) ? "bidirectional" :
+- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+- conn->id, sc, sc->cmnd[0], ctask->itt,
+- scsi_bufflen(sc), scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
++ "cmdsn %d win %d]\n",
++ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
++ conn->id, sc, sc->cmnd[0], ctask->itt, scsi_bufflen(sc),
+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+ }
+@@ -378,12 +298,7 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ conn->session->tt->cleanup_cmd_task(conn, ctask);
+
+ sc->result = err;
+- 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));
+ if (conn->ctask == ctask)
+ conn->ctask = NULL;
+ /* release ref from queuecommand */
+@@ -518,18 +433,6 @@ invalid_datalen:
+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ }
+
+- if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
+- ISCSI_FLAG_CMD_BIDI_OVERFLOW)) {
+- int res_count = be32_to_cpu(rhdr->bi_residual_count);
+-
+- 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;
+- else
+- sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
+-
+ if (rhdr->flags & (ISCSI_FLAG_CMD_UNDERFLOW |
+ ISCSI_FLAG_CMD_OVERFLOW)) {
+ int res_count = be32_to_cpu(rhdr->residual_count);
+@@ -537,11 +440,13 @@ invalid_datalen:
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+ res_count <= scsi_bufflen(sc)))
+- /* write side for bidi or uni-io set_resid */
+ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+- }
++ } else if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
++ ISCSI_FLAG_CMD_BIDI_OVERFLOW))
++ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
++
+ out:
+ debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+ (long)sc, sc->result, ctask->itt);
+@@ -1199,12 +1104,7 @@ reject:
+ fault:
+ spin_unlock(&session->lock);
+ debug_scsi("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));
+ sc->scsi_done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 65d1737..ca7bb6f 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/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,27 +78,25 @@ 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");
+ show_transport_attr(max_lun, "%d");
+@@ -106,11 +104,11 @@ show_transport_attr(max_conn, "%d");
+ show_transport_attr(max_cmd_len, "%d");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
+- &dev_attr_max_lun.attr,
+- &dev_attr_max_conn.attr,
+- &dev_attr_max_cmd_len.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
++ &class_device_attr_max_lun.attr,
++ &class_device_attr_max_conn.attr,
++ &class_device_attr_max_cmd_len.attr,
+ NULL,
+ };
+
+@@ -121,7 +119,7 @@ static struct attribute_group iscsi_transport_group = {
+
+
+ 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_host *ihost = shost->shost_data;
+@@ -141,7 +139,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+ }
+
+ static int iscsi_remove_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_host *ihost = shost->shost_data;
+@@ -1339,8 +1337,11 @@ iscsi_if_rx(struct sk_buff *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)
+
+ /*
+@@ -1348,10 +1349,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); \
+ }
+@@ -1375,16 +1375,17 @@ 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); \
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+ struct iscsi_transport *t = session->transport; \
+ \
+ if (perm && !capable(CAP_SYS_ADMIN)) \
+@@ -1416,10 +1417,9 @@ iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
+ iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 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,
+@@ -1427,11 +1427,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); \
+ }
+
+@@ -1446,10 +1444,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); \
+ }
+@@ -1466,7 +1463,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)
+
+@@ -1474,7 +1471,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)
+@@ -1482,7 +1479,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)
+@@ -1490,7 +1487,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)
+@@ -1581,15 +1578,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->iscsi_transport = tt;
+ priv->t.user_scan = iscsi_user_scan;
+
+- priv->dev.class = &iscsi_transport_class;
+- snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%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];
+@@ -1666,8 +1663,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);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1694,8 +1691,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;
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index cd3ca63..7b90b63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,7 +225,6 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
+- uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.3.8
+
diff --git a/kernel_patches/backport/2.6.18_FC6/iscsi_02_count_fmr_align_violations.patch b/kernel_patches/backport/2.6.18_FC6/iscsi_02_count_fmr_align_violations.patch
new file mode 100644
index 0000000..9bf2d19
--- /dev/null
+++ b/kernel_patches/backport/2.6.18_FC6/iscsi_02_count_fmr_align_violations.patch
@@ -0,0 +1,24 @@
+From 02753dd2caabfe6b1885cb80a8fb8532b416108d Mon Sep 17 00:00:00 2001
+From: Eli Dorfman <elid at voltaire.com>
+Date: Tue, 29 Apr 2008 10:12:39 +0300
+Subject: [PATCH] IB/iSER: Count fmr alignment violations per session
+
+Count fmr alignment violations per session
+as part of the iscsi statistics.
+
+Signed-off-by: Eli Dorfman <elid at voltaire.com>
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 7b90b63..cd3ca63 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -225,6 +225,7 @@ struct iscsi_conn {
+
+ /* custom statistics */
+ uint32_t eh_abort_cnt;
++ uint32_t fmr_unalign_cnt;
+ };
+
+ struct iscsi_pool {
+--
+1.5.5
+
diff --git a/kernel_patches/backport/2.6.18_FC6/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch b/kernel_patches/backport/2.6.18_FC6/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
new file mode 100644
index 0000000..798571f
--- /dev/null
+++ b/kernel_patches/backport/2.6.18_FC6/iscsi_03_copmat_patch_for_RHEL5_and_SLES10.patch
@@ -0,0 +1,151 @@
+From 66ab30f8dadef133bd04bbdcb434a7f742821bed Mon Sep 17 00:00:00 2001
+From: Doron Shoham <dorons at voltaire.com>
+Date: Sun, 29 Jun 2008 15:41:12 +0300
+Subject: [PATCH] copmat patch for RHEL5 and SLES10
+
+Signed-off-by: Doron Shoham <dorons at voltaire.com>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 93 ++++++++++++++++++++---------------
+ 1 files changed, 54 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ca7bb6f..0ccd7e2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -20,6 +20,8 @@
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
++#include <linux/version.h>
++#include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <net/tcp.h>
+@@ -397,10 +399,12 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ * the async scanning code (drivers like iscsi_tcp do login and
+ * scanning from userspace).
+ */
+- if (shost->hostt->scan_finished) {
+- if (queue_work(ihost->scan_workq, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
++ if (shost->hostt->scan_finished) {
++ if (queue_work(ihost->scan_workq, &session->scan_work))
++ atomic_inc(&ihost->nr_scans);
++ }
++#endif
+ }
+
+ /**
+@@ -1294,45 +1298,56 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ * 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)
+ {
++ struct sk_buff *skb;
++
+ mutex_lock(&rx_queue_mutex);
+- while (skb->len >= NLMSG_SPACE(0)) {
+- int err;
+- uint32_t rlen;
+- struct nlmsghdr *nlh;
+- struct iscsi_uevent *ev;
+-
+- nlh = nlmsg_hdr(skb);
+- if (nlh->nlmsg_len < sizeof(*nlh) ||
+- skb->len < nlh->nlmsg_len) {
+- break;
++ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
++ if (NETLINK_CREDS(skb)->uid) {
++ skb_pull(skb, skb->len);
++ goto free_skb;
+ }
+
+- ev = NLMSG_DATA(nlh);
+- rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+- if (rlen > skb->len)
+- rlen = skb->len;
++ while (skb->len >= NLMSG_SPACE(0)) {
++ int err;
++ uint32_t rlen;
++ struct nlmsghdr *nlh;
++ struct iscsi_uevent *ev;
+
+- err = iscsi_if_recv_msg(skb, nlh);
+- 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)
++ nlh = nlmsg_hdr(skb);
++ if (nlh->nlmsg_len < sizeof(*nlh) ||
++ skb->len < nlh->nlmsg_len) {
+ break;
+- err = iscsi_if_send_reply(
+- NETLINK_CREDS(skb)->pid, 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);
++ 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(
++ NETLINK_CREDS(skb)->pid, 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);
+ }
+@@ -1738,7 +1753,7 @@ static __init int iscsi_transport_init(void)
+ return 0;
+
+ release_nls:
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ unregister_session_class:
+ transport_class_unregister(&iscsi_session_class);
+ unregister_conn_class:
+@@ -1753,7 +1768,7 @@ unregister_transport_class:
+ static void __exit iscsi_transport_exit(void)
+ {
+ destroy_workqueue(iscsi_eh_timer_workq);
+- netlink_kernel_release(nls);
++ sock_release(nls->sk_socket);
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
+--
+1.5.3.8
+
--
1.5.3.8
More information about the ewg
mailing list