summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2009-05-14 18:32:59 -0400
committerMike Christie <michaelc@cs.wisc.edu>2009-05-14 18:33:28 -0400
commit6fc020102775dd54c0f76f5107cec72a78ca68ee (patch)
tree089be297a7e09999ce37969416579ed90425b939 /kernel
parenta236f029ac96c621873a25079d56e0b5bf8a959d (diff)
downloadopen-iscsi-6fc020102775dd54c0f76f5107cec72a78ca68ee.tar.gz
kernel: update 2.6.14 - .23 support
Update 2.6.14 - .23 support. Note: 2.6.16 and below is still broken. Please email the open-iscsi list if you need this.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/2.6.14-23_compat.patch1102
-rw-r--r--kernel/Makefile40
2 files changed, 1117 insertions, 25 deletions
diff --git a/kernel/2.6.14-23_compat.patch b/kernel/2.6.14-23_compat.patch
new file mode 100644
index 0000000..ab233bb
--- /dev/null
+++ b/kernel/2.6.14-23_compat.patch
@@ -0,0 +1,1102 @@
+diff --git a/iscsi_tcp.c b/iscsi_tcp.c
+index caa116c..71df5b9 100644
+--- a/iscsi_tcp.c
++++ b/iscsi_tcp.c
+@@ -456,11 +456,9 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task,
+ if (!task->sc)
+ iscsi_sw_tcp_send_linear_data_prep(conn, task->data, count);
+ else {
+- struct scsi_data_buffer *sdb = scsi_out(task->sc);
+-
+- err = iscsi_sw_tcp_send_data_prep(conn, sdb->table.sgl,
+- sdb->table.nents, offset,
+- count);
++ err = iscsi_sw_tcp_send_data_prep(conn, scsi_sglist(task->sc),
++ scsi_sg_count(task->sc),
++ offset, count);
+ }
+
+ if (err) {
+@@ -793,7 +791,11 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
+ shost->max_lun = iscsi_max_lun;
+ shost->max_id = 0;
+ shost->max_channel = 0;
++#ifndef SCSI_MAX_VARLEN_CDB_SIZE
++ shost->max_cmd_len = 16;
++#else
+ shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
++#endif
+
+ if (iscsi_host_add(shost, NULL))
+ goto free_host;
+@@ -832,12 +834,6 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+ iscsi_host_free(shost);
+ }
+
+-static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
+-{
+- set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
+- return 0;
+-}
+-
+ static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
+ {
+ blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
+@@ -846,6 +842,9 @@ static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
+ }
+
+ static struct scsi_host_template iscsi_sw_tcp_sht = {
++#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,24)
++ .use_sg_chaining = ENABLE_SG_CHAINING,
++#endif
+ .module = THIS_MODULE,
+ .name = "iSCSI Initiator over TCP/IP",
+ .queuecommand = iscsi_queuecommand,
+@@ -856,9 +855,8 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+ .eh_abort_handler = iscsi_eh_abort,
+ .eh_device_reset_handler= iscsi_eh_device_reset,
+- .eh_target_reset_handler= iscsi_eh_target_reset,
++ .eh_host_reset_handler = iscsi_eh_target_reset,
+ .use_clustering = DISABLE_CLUSTERING,
+- .slave_alloc = iscsi_sw_tcp_slave_alloc,
+ .slave_configure = iscsi_sw_tcp_slave_configure,
+ .target_alloc = iscsi_target_alloc,
+ .proc_name = "iscsi_tcp",
+diff --git a/iscsi_tcp.h b/iscsi_tcp.h
+index f9a4044..ab20530 100644
+--- a/iscsi_tcp.h
++++ b/iscsi_tcp.h
+@@ -22,6 +22,8 @@
+ #ifndef ISCSI_SW_TCP_H
+ #define ISCSI_SW_TCP_H
+
++#include "open_iscsi_compat.h"
++
+ #include "libiscsi.h"
+ #include "libiscsi_tcp.h"
+
+diff --git a/libiscsi.c b/libiscsi.c
+index fe4b66e..6217f76 100644
+--- a/libiscsi.c
++++ b/libiscsi.c
+@@ -24,7 +24,10 @@
+ #include <linux/types.h>
+ #include <linux/kfifo.h>
+ #include <linux/delay.h>
++#include <linux/version.h>
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)
+ #include <linux/log2.h>
++#endif
+ #include <asm/unaligned.h>
+ #include <net/tcp.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -60,6 +63,8 @@ MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. "
+ __func__, ##arg); \
+ } while (0);
+
++#include "open_iscsi_compat.h"
++
+ /* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
+ #define SNA32_CHECK 2147483648UL
+
+@@ -229,7 +234,7 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
+ sizeof(rlen_ahdr->reserved));
+ rlen_ahdr->ahstype = ISCSI_AHSTYPE_RLENGTH;
+ rlen_ahdr->reserved = 0;
+- rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
++ rlen_ahdr->read_length = cpu_to_be32(scsi_bufflen(sc));
+
+ ISCSI_DBG_SESSION(task->conn->session,
+ "bidi-in rlen_ahdr->read_length(%d) "
+@@ -300,7 +305,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ return rc;
+ }
+ if (sc->sc_data_direction == DMA_TO_DEVICE) {
+- unsigned out_len = scsi_out(sc)->length;
++ unsigned out_len = scsi_bufflen(sc);
+ struct iscsi_r2t_info *r2t = &task->unsol_r2t;
+
+ hdr->data_length = cpu_to_be32(out_len);
+@@ -346,7 +351,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ } else {
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ zero_data(hdr->dlength);
+- hdr->data_length = cpu_to_be32(scsi_in(sc)->length);
++ hdr->data_length = cpu_to_be32(scsi_bufflen(sc));
+
+ if (sc->sc_data_direction == DMA_FROM_DEVICE)
+ hdr->flags |= ISCSI_FLAG_CMD_READ;
+@@ -373,7 +378,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
+ sc->sc_data_direction == DMA_TO_DEVICE ?
+ "write" : "read", conn->id, sc, sc->cmnd[0],
+ task->itt, scsi_bufflen(sc),
+- scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
++ scsi_bidi_cmnd(sc) ? scsi_bufflen(sc) : 0,
+ session->cmdsn,
+ session->max_cmdsn - session->exp_cmdsn + 1);
+ return 0;
+@@ -510,12 +515,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
+ state = ISCSI_TASK_ABRT_TMF;
+
+ sc->result = err << 16;
+- if (!scsi_bidi_cmnd(sc))
+- scsi_set_resid(sc, scsi_bufflen(sc));
+- else {
+- scsi_out(sc)->resid = scsi_out(sc)->length;
+- scsi_in(sc)->resid = scsi_in(sc)->length;
+- }
++ scsi_set_resid(sc, scsi_bufflen(sc));
+
+ iscsi_complete_task(task, state);
+ }
+@@ -706,7 +706,7 @@ invalid_datalen:
+ goto out;
+ }
+
+- senselen = get_unaligned_be16(data);
++ senselen = be16_to_cpu(get_unaligned((__be16 *) data));
+ if (datalen < senselen)
+ goto invalid_datalen;
+
+@@ -723,8 +723,8 @@ invalid_datalen:
+
+ if (scsi_bidi_cmnd(sc) && res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_BIDI_OVERFLOW ||
+- res_count <= scsi_in(sc)->length))
+- scsi_in(sc)->resid = res_count;
++ res_count <= scsi_bufflen(sc)))
++ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+ }
+@@ -773,8 +773,8 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+
+ if (res_count > 0 &&
+ (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW ||
+- res_count <= scsi_in(sc)->length))
+- scsi_in(sc)->resid = res_count;
++ res_count <= scsi_bufflen(sc)))
++ scsi_set_resid(sc, res_count);
+ else
+ sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+ }
+@@ -1498,12 +1498,7 @@ fault:
+ spin_unlock(&session->lock);
+ ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
+ sc->cmnd[0], reason);
+- if (!scsi_bidi_cmnd(sc))
+- scsi_set_resid(sc, scsi_bufflen(sc));
+- else {
+- scsi_out(sc)->resid = scsi_out(sc)->length;
+- scsi_in(sc)->resid = scsi_in(sc)->length;
+- }
++ scsi_set_resid(sc, scsi_bufflen(sc));
+ done(sc);
+ spin_lock(host->host_lock);
+ return 0;
+diff --git a/libiscsi.h b/libiscsi.h
+index 1798fbe..c9174ec 100644
+--- a/libiscsi.h
++++ b/libiscsi.h
+@@ -32,6 +32,8 @@
+ #include "iscsi_if.h"
+ #include "scsi_transport_iscsi.h"
+
++#include "open_iscsi_compat.h"
++
+ struct scsi_transport_template;
+ struct scsi_host_template;
+ struct scsi_device;
+diff --git a/libiscsi_tcp.c b/libiscsi_tcp.c
+index c2b535b..76ead4b 100644
+--- a/libiscsi_tcp.c
++++ b/libiscsi_tcp.c
+@@ -360,6 +360,16 @@ iscsi_segment_seek_sg(struct iscsi_segment *segment,
+ struct scatterlist *sg;
+ unsigned int i;
+
++ /*
++ * older kernels could send use_sg=0 for commands like sgio
++ * or scsi-ml commands.
++ */
++ if (!sg_count) {
++ iscsi_segment_init_linear(segment, (void *)sg_list + offset,
++ size, done, hash);
++ return 0;
++ }
++
+ __iscsi_segment_init(segment, size, done, hash);
+ for_each_sg(sg_list, sg, sg_count, i) {
+ if (offset < sg->length) {
+@@ -471,7 +481,7 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
+ struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
+ int datasn = be32_to_cpu(rhdr->datasn);
+- unsigned total_in_length = scsi_in(task->sc)->length;
++ unsigned total_in_length = scsi_bufflen(task->sc);
+
+ /*
+ * lib iscsi will update this in the completion handling if there
+@@ -565,11 +575,11 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
+ r2t->data_length, session->max_burst);
+
+ r2t->data_offset = be32_to_cpu(rhdr->data_offset);
+- if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
++ if (r2t->data_offset + r2t->data_length > scsi_bufflen(task->sc)) {
+ iscsi_conn_printk(KERN_ERR, conn,
+ "invalid R2T with data len %u at offset %u "
+ "and total length %d\n", r2t->data_length,
+- r2t->data_offset, scsi_out(task->sc)->length);
++ r2t->data_offset, scsi_bufflen(task->sc));
+ __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
+ sizeof(void*));
+ return ISCSI_ERR_DATALEN;
+@@ -668,7 +678,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ if (tcp_conn->in.datalen) {
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
+ struct hash_desc *rx_hash = NULL;
+- struct scsi_data_buffer *sdb = scsi_in(task->sc);
+
+ /*
+ * Setup copy of Data-In into the Scsi_Cmnd
+@@ -687,8 +696,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+ tcp_task->data_offset,
+ tcp_conn->in.datalen);
+ rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
+- sdb->table.sgl,
+- sdb->table.nents,
++ scsi_sglist(task->sc),
++ scsi_sg_count(task->sc),
+ tcp_task->data_offset,
+ tcp_conn->in.datalen,
+ iscsi_tcp_process_data_in,
+diff --git a/libiscsi_tcp.h b/libiscsi_tcp.h
+index 3bacef5..5ea284d 100644
+--- a/libiscsi_tcp.h
++++ b/libiscsi_tcp.h
+@@ -21,6 +21,7 @@
+ #ifndef LIBISCSI_TCP_H
+ #define LIBISCSI_TCP_H
+
++#include "open_iscsi_compat.h"
+ #include "libiscsi.h"
+
+ struct iscsi_tcp_conn;
+diff --git a/open_iscsi_compat.h b/open_iscsi_compat.h
+new file mode 100644
+index 0000000..763d07a
+--- /dev/null
++++ b/open_iscsi_compat.h
+@@ -0,0 +1,321 @@
++#ifndef OPEN_ISCSI_COMPAT
++#define OPEN_ISCSI_COMPAT
++
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <scsi/scsi.h>
++#include <scsi/scsi_cmnd.h>
++
++#ifndef SCAN_WILD_CARD
++#define SCAN_WILD_CARD ~0
++#endif
++
++#ifndef NIPQUAD_FMT
++#define NIPQUAD_FMT "%u.%u.%u.%u"
++#endif
++
++#ifndef NIP6_FMT
++#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
++#endif
++
++#ifndef DEFINE_MUTEX
++
++/* mutex changes from 2.6.16-rc1 and up */
++#define DEFINE_MUTEX DECLARE_MUTEX
++#define mutex_lock down
++#define mutex_unlock up
++#define mutex semaphore
++#define mutex_init init_MUTEX
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,19)
++struct delayed_work {
++ struct work_struct work;
++};
++
++#define cancel_delayed_work(_dwork) cancel_delayed_work(&(_dwork)->work)
++
++static inline void INIT_WORK_compat(struct work_struct *work, void *func)
++{
++ INIT_WORK(work, func, work);
++}
++
++#undef INIT_WORK
++#define INIT_WORK(_work, _func) INIT_WORK_compat(_work, _func)
++#define INIT_DELAYED_WORK(_work,_func) INIT_WORK(&(_work)->work, _func)
++
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12)
++
++void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
++{
++ int i;
++
++ memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
++
++ for (i = 0; i < sizeof(lun); i += 2) {
++ scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
++ scsilun->scsi_lun[i+1] = lun & 0xFF;
++ lun = lun >> 16;
++ }
++}
++
++#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
++ __nlmsg_put(skb, daemon_pid, 0, 0, len)
++
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
++
++#define gfp_t unsigned
++
++void *kzalloc(size_t size, gfp_t flags)
++{
++ void *ret = kmalloc(size, flags);
++ if (ret)
++ memset(ret, 0, size);
++}
++
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
++
++#include "linux/crypto.h"
++
++#define CRYPTO_ALG_ASYNC 0x00000080
++struct hash_desc
++{
++ struct crypto_tfm *tfm;
++ u32 flags;
++};
++
++static inline int crypto_hash_init(struct hash_desc *desc)
++{
++ crypto_digest_init(desc->tfm);
++ return 0;
++}
++
++static inline int crypto_hash_digest(struct hash_desc *desc,
++ struct scatterlist *sg,
++ unsigned int nbytes, u8 *out)
++{
++ crypto_digest_digest(desc->tfm, sg, 1, out);
++ return nbytes;
++}
++
++static inline int crypto_hash_update(struct hash_desc *desc,
++ struct scatterlist *sg,
++ unsigned int nbytes)
++{
++ crypto_digest_update(desc->tfm, sg, 1);
++ return nbytes;
++}
++
++static inline int crypto_hash_final(struct hash_desc *desc, u8 *out)
++{
++ crypto_digest_final(desc->tfm, out);
++ return 0;
++}
++
++static inline struct crypto_tfm *crypto_alloc_hash(const char *alg_name,
++ u32 type, u32 mask)
++{
++ struct crypto_tfm *ret = crypto_alloc_tfm(alg_name ,type);
++ return ret ? ret : ERR_PTR(-ENOMEM);
++}
++
++static inline void crypto_free_hash(struct crypto_tfm *tfm)
++{
++ crypto_free_tfm(tfm);
++}
++
++int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
++ int *addrlen)
++{
++ return sock->ops->getname(sock, addr, addrlen, 0);
++}
++
++int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
++ int *addrlen)
++{
++ return sock->ops->getname(sock, addr, addrlen, 1);
++}
++
++#endif
++
++#ifndef bool
++#define bool int
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20)
++#ifdef RHEL_RELEASE_VERSION
++#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2)
++static inline int is_power_of_2(unsigned long n)
++{
++ return (n != 0 && ((n & (n - 1)) == 0));
++}
++#endif
++#else
++/* not a redhat kernel */
++static inline int is_power_of_2(unsigned long n)
++{
++ return (n != 0 && ((n & (n - 1)) == 0));
++}
++#endif
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
++
++static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
++{
++ return (struct nlmsghdr *)skb->data;
++}
++
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
++#ifdef RHEL_RELEASE_VERSION
++#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2)
++static inline void *shost_priv(struct Scsi_Host *shost)
++{
++ return (void *)shost->hostdata;
++}
++#endif
++#else
++/* not a redhat kernel */
++static inline void *shost_priv(struct Scsi_Host *shost)
++{
++ return (void *)shost->hostdata;
++}
++#endif
++
++/*
++ * Note: We do not support bidi for the compat modules if the kernel
++ * does not have support.
++ */
++#define scsi_sg_count(cmd) ((cmd)->use_sg)
++#define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
++#define scsi_bufflen(cmd) ((cmd)->request_bufflen)
++
++#ifdef RHEL_RELEASE_VERSION
++#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2)
++static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
++{
++ cmd->resid = resid;
++}
++
++static inline int scsi_get_resid(struct scsi_cmnd *cmd)
++{
++ return cmd->resid;
++}
++#endif
++#else
++/* not a redhat kernel */
++static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid)
++{
++ cmd->resid = resid;
++}
++
++static inline int scsi_get_resid(struct scsi_cmnd *cmd)
++{
++ return cmd->resid;
++}
++#endif
++
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
++
++static inline unsigned long rounddown_pow_of_two(unsigned long n)
++{
++ return 1UL << (fls_long(n) - 1);
++}
++
++
++static inline struct scatterlist *sg_next(struct scatterlist *sg)
++{
++ if (!sg) {
++ BUG();
++ return NULL;
++ }
++ return sg + 1;
++}
++
++#define for_each_sg(sglist, sg, nr, __i) \
++ for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
++
++#define sg_page(_sg) _sg->page
++
++static inline void sg_set_page(struct scatterlist *sg, struct page *page,
++ unsigned int len, unsigned int offset)
++{
++ sg->page = page;
++ sg->offset = offset;
++ sg->length = len;
++}
++
++static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
++{
++ memset(sgl, 0, sizeof(*sgl) * nents);
++}
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)
++
++static inline int scsi_bidi_cmnd(struct scsi_cmnd *cmd)
++{
++ return 0;
++}
++
++#define netlink_kernel_release(_nls) \
++ sock_release(_nls->sk_socket)
++
++
++#endif
++
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
++
++#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
++ netlink_kernel_create(uint, input)
++
++#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
++
++#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
++ netlink_kernel_create(uint, groups, input, mod)
++
++#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
++
++#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
++ netlink_kernel_create(uint, groups, input, cb_mutex, mod)
++
++#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
++
++#define netlink_kernel_create(net, uint, groups, input, cb_mutex, mod) \
++ netlink_kernel_create(uint, groups, input, cb_mutex, mod)
++
++#endif
++
++#ifndef DID_TRANSPORT_DISRUPTED
++#define DID_TRANSPORT_DISRUPTED DID_BUS_BUSY
++#endif
++
++#ifndef DID_TRANSPORT_FAILFAST
++#define DID_TRANSPORT_FAILFAST DID_NO_CONNECT
++#endif
++
++#ifndef SCSI_MLQUEUE_TARGET_BUSY
++#define SCSI_MLQUEUE_TARGET_BUSY SCSI_MLQUEUE_HOST_BUSY
++#endif
++
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)
++
++#define BLK_EH_NOT_HANDLED EH_NOT_HANDLED
++#define BLK_EH_RESET_TIMER EH_RESET_TIMER
++
++#define blk_eh_timer_return scsi_eh_timer_return
++
++#endif
++
++#endif
+diff --git a/scsi_transport_iscsi.c b/scsi_transport_iscsi.c
+index c9e95e7..79436c4 100644
+--- a/scsi_transport_iscsi.c
++++ b/scsi_transport_iscsi.c
+@@ -41,13 +41,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 */
+@@ -64,12 +64,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);
+ }
+
+@@ -79,33 +79,31 @@ static void iscsi_transport_release(struct device *dev)
+ */
+ static struct class iscsi_transport_class = {
+ .name = "iscsi_transport",
+- .dev_release = iscsi_transport_release,
++ .release = iscsi_transport_release,
+ };
+
+ static ssize_t
+-show_transport_handle(struct device *dev, struct device_attribute *attr,
+- char *buf)
++show_transport_handle(struct class_device *cdev, char *buf)
+ {
+- struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
++ struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+ return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport));
+ }
+-static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
++static CLASS_DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
+
+ #define show_transport_attr(name, format) \
+ static ssize_t \
+-show_transport_##name(struct device *dev, \
+- struct device_attribute *attr,char *buf) \
++show_transport_##name(struct class_device *cdev, char *buf) \
+ { \
+- struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \
++ struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev); \
+ return sprintf(buf, format"\n", priv->iscsi_transport->name); \
+ } \
+-static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
++static CLASS_DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
+
+ show_transport_attr(caps, "0x%x");
+
+ static struct attribute *iscsi_transport_attrs[] = {
+- &dev_attr_handle.attr,
+- &dev_attr_caps.attr,
++ &class_device_attr_handle.attr,
++ &class_device_attr_caps.attr,
+ NULL,
+ };
+
+@@ -113,6 +111,7 @@ static struct attribute_group iscsi_transport_group = {
+ .attrs = iscsi_transport_attrs,
+ };
+
++#if 0
+ /*
+ * iSCSI endpoint attrs
+ */
+@@ -236,9 +235,10 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ return ep;
+ }
+ EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
++#endif
+
+ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+- struct device *cdev)
++ struct class_device *cdev)
+ {
+ struct Scsi_Host *shost = dev_to_shost(dev);
+ struct iscsi_cls_host *ihost = shost->shost_data;
+@@ -545,15 +545,6 @@ static void __iscsi_unblock_session(struct work_struct *work)
+ spin_unlock_irqrestore(&session->lock, flags);
+ /* start IO */
+ scsi_target_unblock(&session->dev);
+- /*
+- * Only do kernel scanning if the driver is properly hooked into
+- * the async scanning code (drivers like iscsi_tcp do login and
+- * scanning from userspace).
+- */
+- if (shost->hostt->scan_finished) {
+- if (scsi_queue_work(shost, &session->scan_work))
+- atomic_inc(&ihost->nr_scans);
+- }
+ }
+
+ /**
+@@ -698,7 +689,8 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
+ }
+ session->target_id = id;
+
+- dev_set_name(&session->dev, "session%u", session->sid);
++ snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
++ session->sid);
+ err = device_add(&session->dev);
+ if (err) {
+ iscsi_cls_session_printk(KERN_ERR, session,
+@@ -870,7 +862,8 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ if (!get_device(&session->dev))
+ goto free_conn;
+
+- dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
++ snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
++ session->sid, cid);
+ conn->dev.parent = &session->dev;
+ conn->dev.release = iscsi_conn_release;
+ err = device_register(&conn->dev);
+@@ -1309,6 +1302,8 @@ static int
+ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev, int msg_type)
+ {
++ return -ENOSYS;
++#if 0
+ struct iscsi_endpoint *ep;
+ int rc = 0;
+
+@@ -1340,6 +1335,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ break;
+ }
+ return rc;
++
++#endif
+ }
+
+ static int
+@@ -1421,6 +1418,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ ev->u.c_session.queue_depth);
+ break;
+ case ISCSI_UEVENT_CREATE_BOUND_SESSION:
++ err = -ENOSYS;
++ break;
++#if 0
+ ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
+ if (!ep) {
+ err = -EINVAL;
+@@ -1432,6 +1432,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ ev->u.c_bound_session.cmds_max,
+ ev->u.c_bound_session.queue_depth);
+ break;
++#endif
+ case ISCSI_UEVENT_DESTROY_SESSION:
+ session = iscsi_session_lookup(ev->u.d_session.sid);
+ if (session)
+@@ -1516,55 +1517,70 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+ }
+
+ /*
+- * Get message from skb. Each message is processed by iscsi_if_recv_msg.
+- * Malformed skbs with wrong lengths or invalid creds are not processed.
++ * Get message from skb (based on rtnetlink_rcv_skb). Each message is
++ * processed by iscsi_if_recv_msg. Malformed skbs with wrong lengths or
++ * invalid creds are discarded silently.
+ */
+ 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);
+ }
+
++#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)
+
+ /*
+@@ -1572,10 +1588,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); \
+ }
+@@ -1599,16 +1614,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)) \
+@@ -1642,10 +1658,9 @@ iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
+ iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0)
+
+ static ssize_t
+-show_priv_session_state(struct device *dev, struct device_attribute *attr,
+- char *buf)
++show_priv_session_state(struct class_device *cdev, char *buf)
+ {
+- struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
++ struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev);
+ return sprintf(buf, "%s\n", iscsi_session_state_name(session->state));
+ }
+ static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
+@@ -1653,11 +1668,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); \
+ }
+
+@@ -1672,10 +1685,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); \
+ }
+@@ -1692,7 +1704,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)
+
+@@ -1700,7 +1712,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)
+@@ -1708,7 +1720,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)
+@@ -1716,7 +1728,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)
+@@ -1808,15 +1820,15 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ priv->t.user_scan = iscsi_user_scan;
+ priv->t.create_work_queue = 1;
+
+- priv->dev.class = &iscsi_transport_class;
+- dev_set_name(&priv->dev, "%s", tt->name);
+- err = device_register(&priv->dev);
++ priv->cdev.class = &iscsi_transport_class;
++ snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
++ err = class_device_register(&priv->cdev);
+ if (err)
+ goto free_priv;
+
+- err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
++ err = sysfs_create_group(&priv->cdev.kobj, &iscsi_transport_group);
+ if (err)
+- goto unregister_dev;
++ goto unregister_cdev;
+
+ /* host parameters */
+ priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+@@ -1895,9 +1907,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);
+- return NULL;
++unregister_cdev:
++ class_device_unregister(&priv->cdev);
+ free_priv:
+ kfree(priv);
+ return NULL;
+@@ -1924,8 +1935,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;
+@@ -1945,13 +1956,14 @@ static __init int iscsi_transport_init(void)
+ if (err)
+ return err;
+
++#if 0
+ err = class_register(&iscsi_endpoint_class);
+ if (err)
+ goto unregister_transport_class;
+-
++#endif
+ err = transport_class_register(&iscsi_host_class);
+ if (err)
+- goto unregister_endpoint_class;
++ goto unregister_transport_class;
+
+ err = transport_class_register(&iscsi_connection_class);
+ if (err)
+@@ -1982,8 +1994,10 @@ unregister_conn_class:
+ transport_class_unregister(&iscsi_connection_class);
+ unregister_host_class:
+ transport_class_unregister(&iscsi_host_class);
++#if 0
+ unregister_endpoint_class:
+ class_unregister(&iscsi_endpoint_class);
++#endif
+ unregister_transport_class:
+ class_unregister(&iscsi_transport_class);
+ return err;
+@@ -1996,7 +2010,9 @@ static void __exit iscsi_transport_exit(void)
+ transport_class_unregister(&iscsi_connection_class);
+ transport_class_unregister(&iscsi_session_class);
+ transport_class_unregister(&iscsi_host_class);
++#if 0
+ class_unregister(&iscsi_endpoint_class);
++#endif
+ class_unregister(&iscsi_transport_class);
+ }
+
+diff --git a/scsi_transport_iscsi.h b/scsi_transport_iscsi.h
+index 6beea23..d509d17 100644
+--- a/scsi_transport_iscsi.h
++++ b/scsi_transport_iscsi.h
+@@ -28,6 +28,8 @@
+ #include <linux/mutex.h>
+ #include "iscsi_if.h"
+
++#include "open_iscsi_compat.h"
++
+ struct scsi_transport_template;
+ struct iscsi_transport;
+ struct iscsi_endpoint;
+--
+1.5.2.1
+
diff --git a/kernel/Makefile b/kernel/Makefile
index 75671bd..a97c52f 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -49,8 +49,7 @@ all: kernel_check
# form.
#some constants
-14to19_patch=2.6.14-19_compat.patch
-20to21_patch=2.6.20-21_compat.patch
+14to23_patch=2.6.14-23_compat.patch
24_patch=2.6.24_compat.patch
26_patch=2.6.26_compat.patch
27_patch=2.6.27_compat.patch
@@ -69,25 +68,25 @@ KSUBLEVEL = $(shell cat $(KSRC)/Makefile | awk -F= '/^SUBLEVEL =/ {print $$2}' |
KERNEL_TARGET=linux_2_6_$(KSUBLEVEL)
kernel_check: $(KERNEL_TARGET)
-linux_2_6_14: has_14to19_patch
+linux_2_6_14: has_14to23_patch
-linux_2_6_15: has_14to19_patch
+linux_2_6_15: has_14to23_patch
-linux_2_6_16: has_14to19_patch
+linux_2_6_16: has_14to23_patch
-linux_2_6_17: has_14to19_patch
+linux_2_6_17: has_14to23_patch
-linux_2_6_18: has_14to19_patch
+linux_2_6_18: has_14to23_patch
-linux_2_6_19: has_14to19_patch
+linux_2_6_19: has_14to23_patch
-linux_2_6_20: has_20to21_patch
+linux_2_6_20: has_14to23_patch
-linux_2_6_21: has_20to21_patch
+linux_2_6_21: has_14to23_patch
-linux_2_6_22: has_20to21_patch
+linux_2_6_22: has_14to23_patch
-linux_2_6_23: has_20to21_patch
+linux_2_6_23: has_14to23_patch
linux_2_6_24: has_24_patch
@@ -112,22 +111,13 @@ do_unpatch_code:
# these below targets must be the same as the variable name prefixed by has_
# otherwise below compat_patch: target will not work
-has_14to19_patch: $(14to19_patch)
- echo "Patching source code for linux-2.6.14-19 ..."
+has_14to23_patch: $(14to23_patch)
+ echo "Patching source code for linux-2.6.14-23 ..."
if [ -e $(cur_patched) ]; then \
make -C . clean; \
fi
- patch -p1 < $(14to19_patch)
- cp $(14to19_patch) $@
- ln -s $@ $(cur_patched)
-
-has_20to21_patch: $(20to21_patch)
- echo "Patching source code for linux-2.6.20-21 ..."
- if [ -e $(cur_patched) ]; then \
- make -C . clean; \
- fi
- patch -p1 < $(20to21_patch)
- cp $(20to21_patch) $@
+ patch -p1 < $(14to23_patch)
+ cp $(14to23_patch) $@
ln -s $@ $(cur_patched)
has_24_patch: $(24_patch)