diff --git a/iscsi-scst/kernel/config.c b/iscsi-scst/kernel/config.c index c53b592c5..b4294c2fc 100644 --- a/iscsi-scst/kernel/config.c +++ b/iscsi-scst/kernel/config.c @@ -168,7 +168,7 @@ static void iscsi_proc_log_entry_clean(struct scst_tgt_template *templ) struct proc_entries { const char *name; - struct file_operations *fops; + const struct file_operations *const fops; }; static struct proc_entries iscsi_proc_entries[] = @@ -475,7 +475,7 @@ static int release(struct inode *inode, struct file *filp) return 0; } -struct file_operations ctr_fops = { +const struct file_operations ctr_fops = { .owner = THIS_MODULE, .unlocked_ioctl = ioctl, .compat_ioctl = ioctl, diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 238464fbc..1f6e0a112 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -89,9 +89,14 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session) "%u.%u.%u.%u", NIPQUAD(inet_sk(sk)->daddr)); break; case AF_INET6: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) snprintf(buf, sizeof(buf), "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]", NIP6(inet6_sk(sk)->daddr)); +#else + snprintf(buf, sizeof(buf), "[%p6]", + &inet6_sk(sk)->daddr); +#endif break; default: break; @@ -500,7 +505,7 @@ out_err: /* target_mutex supposed to be locked */ int conn_add(struct iscsi_session *session, struct iscsi_kern_conn_info *info) { - struct iscsi_conn *conn, *new_conn; + struct iscsi_conn *conn, *new_conn = NULL; int err; bool reinstatement = false; diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index 3ff334c49..b7f88171c 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -3156,7 +3156,7 @@ static int __init iscsi_init(void) if (err < 0) goto out_reg_tmpl; - num = max(num_online_cpus(), 2); + num = max((int)num_online_cpus(), 2); err = iscsi_run_threads(num, "iscsird", istrd); if (err != 0) diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index ed6c113dd..c0e0d7764 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -387,7 +387,7 @@ struct iscsi_cmnd { extern struct mutex target_mgmt_mutex; -extern struct file_operations ctr_fops; +extern const struct file_operations ctr_fops; extern spinlock_t iscsi_rd_lock; extern struct list_head iscsi_rd_list; @@ -443,14 +443,14 @@ extern void target_del_session(struct iscsi_target *target, extern void target_del_all_sess(struct iscsi_target *target, int flags); extern void target_del_all(void); -extern struct seq_operations iscsi_seq_op; +extern const struct seq_operations iscsi_seq_op; /* config.c */ extern int iscsi_procfs_init(void); extern void iscsi_procfs_exit(void); /* session.c */ -extern struct file_operations session_seq_fops; +extern const struct file_operations session_seq_fops; extern struct iscsi_session *session_lookup(struct iscsi_target *, u64); extern void sess_enable_reinstated_sess(struct iscsi_session *); extern int session_add(struct iscsi_target *, struct iscsi_kern_session_info *); diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.29.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.29.patch new file mode 100644 index 000000000..628a6d815 --- /dev/null +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.29.patch @@ -0,0 +1,360 @@ +diff -upkr linux-2.6.29/include/linux/mm_types.h linux-2.6.29/include/linux/mm_types.h +--- linux-2.6.29/include/linux/mm_types.h 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/include/linux/mm_types.h 2009-03-25 12:13:18.000000000 +0300 +@@ -94,6 +94,18 @@ struct page { + void *virtual; /* Kernel virtual address (NULL if + not kmapped, ie. highmem) */ + #endif /* WANT_PAGE_VIRTUAL */ ++ ++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) ++ /* ++ * Used to implement support for notification on zero-copy TCP transfer ++ * completion. It might look as not good to have this field here and ++ * it's better to have it in struct sk_buff, but it would make the code ++ * much more complicated and fragile, since all skb then would have to ++ * contain only pages with the same value in this field. ++ */ ++ void *net_priv; ++#endif ++ + }; + + /* +diff -upkr linux-2.6.29/include/linux/net.h linux-2.6.29/include/linux/net.h +--- linux-2.6.29/include/linux/net.h 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/include/linux/net.h 2009-03-25 12:13:18.000000000 +0300 +@@ -57,6 +57,7 @@ typedef enum { + #include + #include + #include /* For O_CLOEXEC and O_NONBLOCK */ ++#include + + struct poll_table_struct; + struct pipe_inode_info; +@@ -352,5 +353,44 @@ static const struct proto_ops name##_ops + extern struct ratelimit_state net_ratelimit_state; + #endif + ++#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) ++/* Support for notification on zero-copy TCP transfer completion */ ++typedef void (*net_get_page_callback_t)(struct page *page); ++typedef void (*net_put_page_callback_t)(struct page *page); ++ ++extern net_get_page_callback_t net_get_page_callback; ++extern net_put_page_callback_t net_put_page_callback; ++ ++extern int net_set_get_put_page_callbacks( ++ net_get_page_callback_t get_callback, ++ net_put_page_callback_t put_callback); ++ ++/* ++ * See comment for net_set_get_put_page_callbacks() why those functions ++ * don't need any protection. ++ */ ++static inline void net_get_page(struct page *page) ++{ ++ if (page->net_priv != 0) ++ net_get_page_callback(page); ++ get_page(page); ++} ++static inline void net_put_page(struct page *page) ++{ ++ if (page->net_priv != 0) ++ net_put_page_callback(page); ++ put_page(page); ++} ++#else ++static inline void net_get_page(struct page *page) ++{ ++ get_page(page); ++} ++static inline void net_put_page(struct page *page) ++{ ++ put_page(page); ++} ++#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */ ++ + #endif /* __KERNEL__ */ + #endif /* _LINUX_NET_H */ +diff -upkr linux-2.6.29/net/core/skbuff.c linux-2.6.29/net/core/skbuff.c +--- linux-2.6.29/net/core/skbuff.c 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/core/skbuff.c 2009-03-25 13:57:33.000000000 +0300 +@@ -73,13 +73,13 @@ static struct kmem_cache *skbuff_fclone_ + static void sock_pipe_buf_release(struct pipe_inode_info *pipe, + struct pipe_buffer *buf) + { +- put_page(buf->page); ++ net_put_page(buf->page); + } + + static void sock_pipe_buf_get(struct pipe_inode_info *pipe, + struct pipe_buffer *buf) + { +- get_page(buf->page); ++ net_get_page(buf->page); + } + + static int sock_pipe_buf_steal(struct pipe_inode_info *pipe, +@@ -327,7 +327,7 @@ static void skb_release_data(struct sk_b + if (skb_shinfo(skb)->nr_frags) { + int i; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) +- put_page(skb_shinfo(skb)->frags[i].page); ++ net_put_page(skb_shinfo(skb)->frags[i].page); + } + + if (skb_shinfo(skb)->frag_list) +@@ -716,7 +716,7 @@ struct sk_buff *pskb_copy(struct sk_buff + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; +- get_page(skb_shinfo(n)->frags[i].page); ++ net_get_page(skb_shinfo(n)->frags[i].page); + } + skb_shinfo(n)->nr_frags = i; + } +@@ -781,7 +781,7 @@ int pskb_expand_head(struct sk_buff *skb + sizeof(struct skb_shared_info)); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) +- get_page(skb_shinfo(skb)->frags[i].page); ++ net_get_page(skb_shinfo(skb)->frags[i].page); + + if (skb_shinfo(skb)->frag_list) + skb_clone_fraglist(skb); +@@ -1050,7 +1050,7 @@ drop_pages: + skb_shinfo(skb)->nr_frags = i; + + for (; i < nfrags; i++) +- put_page(skb_shinfo(skb)->frags[i].page); ++ net_put_page(skb_shinfo(skb)->frags[i].page); + + if (skb_shinfo(skb)->frag_list) + skb_drop_fraglist(skb); +@@ -1219,7 +1219,7 @@ pull_pages: + k = 0; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + if (skb_shinfo(skb)->frags[i].size <= eat) { +- put_page(skb_shinfo(skb)->frags[i].page); ++ net_put_page(skb_shinfo(skb)->frags[i].page); + eat -= skb_shinfo(skb)->frags[i].size; + } else { + skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i]; +@@ -1322,7 +1322,7 @@ fault: + */ + static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) + { +- put_page(spd->pages[i]); ++ net_put_page(spd->pages[i]); + } + + static inline struct page *linear_to_page(struct page *page, unsigned int len, +@@ -1352,7 +1352,7 @@ static inline int spd_fill_page(struct s + if (!page) + return 1; + } else +- get_page(page); ++ net_get_page(page); + + spd->pages[spd->nr_pages] = page; + spd->partial[spd->nr_pages].len = len; +@@ -1977,7 +1977,7 @@ static inline void skb_split_no_header(s + * where splitting is expensive. + * 2. Split is accurately. We make this. + */ +- get_page(skb_shinfo(skb)->frags[i].page); ++ net_get_page(skb_shinfo(skb)->frags[i].page); + skb_shinfo(skb1)->frags[0].page_offset += len - pos; + skb_shinfo(skb1)->frags[0].size -= len - pos; + skb_shinfo(skb)->frags[i].size = len - pos; +@@ -2098,7 +2098,7 @@ int skb_shift(struct sk_buff *tgt, struc + to++; + + } else { +- get_page(fragfrom->page); ++ net_get_page(fragfrom->page); + fragto->page = fragfrom->page; + fragto->page_offset = fragfrom->page_offset; + fragto->size = todo; +@@ -2120,7 +2120,7 @@ int skb_shift(struct sk_buff *tgt, struc + fragto = &skb_shinfo(tgt)->frags[merge]; + + fragto->size += fragfrom->size; +- put_page(fragfrom->page); ++ net_put_page(fragfrom->page); + } + + /* Reposition in the original skb */ +@@ -2514,7 +2514,7 @@ struct sk_buff *skb_segment(struct sk_bu + + while (pos < offset + len && i < nfrags) { + *frag = skb_shinfo(skb)->frags[i]; +- get_page(frag->page); ++ net_get_page(frag->page); + size = frag->size; + + if (pos < offset) { +diff -upkr linux-2.6.29/net/ipv4/ip_output.c linux-2.6.29/net/ipv4/ip_output.c +--- linux-2.6.29/net/ipv4/ip_output.c 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/ipv4/ip_output.c 2009-03-25 12:13:18.000000000 +0300 +@@ -1013,7 +1013,7 @@ alloc_new_skb: + err = -EMSGSIZE; + goto error; + } +- get_page(page); ++ net_get_page(page); + skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); + frag = &skb_shinfo(skb)->frags[i]; + } +@@ -1171,7 +1171,7 @@ ssize_t ip_append_page(struct sock *sk, + if (skb_can_coalesce(skb, i, page, offset)) { + skb_shinfo(skb)->frags[i-1].size += len; + } else if (i < MAX_SKB_FRAGS) { +- get_page(page); ++ net_get_page(page); + skb_fill_page_desc(skb, i, page, offset, len); + } else { + err = -EMSGSIZE; +diff -upkr linux-2.6.29/net/ipv4/Makefile linux-2.6.29/net/ipv4/Makefile +--- linux-2.6.29/net/ipv4/Makefile 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/ipv4/Makefile 2009-03-25 12:13:18.000000000 +0300 +@@ -49,6 +49,7 @@ obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o + obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o + obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o + obj-$(CONFIG_NETLABEL) += cipso_ipv4.o ++obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o + + obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ + xfrm4_output.o +diff -upkr linux-2.6.29/net/ipv4/tcp.c linux-2.6.29/net/ipv4/tcp.c +--- linux-2.6.29/net/ipv4/tcp.c 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/ipv4/tcp.c 2009-03-25 12:13:18.000000000 +0300 +@@ -720,7 +720,7 @@ new_segment: + if (can_coalesce) { + skb_shinfo(skb)->frags[i - 1].size += copy; + } else { +- get_page(page); ++ net_get_page(page); + skb_fill_page_desc(skb, i, page, offset, copy); + } + +@@ -925,7 +925,7 @@ new_segment: + goto new_segment; + } else if (page) { + if (off == PAGE_SIZE) { +- put_page(page); ++ net_put_page(page); + TCP_PAGE(sk) = page = NULL; + off = 0; + } +@@ -966,9 +966,9 @@ new_segment: + } else { + skb_fill_page_desc(skb, i, page, off, copy); + if (TCP_PAGE(sk)) { +- get_page(page); ++ net_get_page(page); + } else if (off + copy < PAGE_SIZE) { +- get_page(page); ++ net_get_page(page); + TCP_PAGE(sk) = page; + } + } +diff -upkr linux-2.6.29/net/ipv4/tcp_output.c linux-2.6.29/net/ipv4/tcp_output.c +--- linux-2.6.29/net/ipv4/tcp_output.c 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/ipv4/tcp_output.c 2009-03-25 12:13:18.000000000 +0300 +@@ -871,7 +871,7 @@ static void __pskb_trim_head(struct sk_b + k = 0; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + if (skb_shinfo(skb)->frags[i].size <= eat) { +- put_page(skb_shinfo(skb)->frags[i].page); ++ net_put_page(skb_shinfo(skb)->frags[i].page); + eat -= skb_shinfo(skb)->frags[i].size; + } else { + skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i]; +diff -upkr linux-2.6.29/net/ipv4/tcp_zero_copy.c linux-2.6.29/net/ipv4/tcp_zero_copy.c +--- linux-2.6.29/net/ipv4/tcp_zero_copy.c 2009-03-25 14:03:29.000000000 +0300 ++++ linux-2.6.29/net/ipv4/tcp_zero_copy.c 2009-03-25 12:13:18.000000000 +0300 +@@ -0,0 +1,49 @@ ++/* ++ * Support routines for TCP zero copy transmit ++ * ++ * Created by Vladislav Bolkhovitin ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ */ ++ ++#include ++ ++net_get_page_callback_t net_get_page_callback __read_mostly; ++EXPORT_SYMBOL(net_get_page_callback); ++ ++net_put_page_callback_t net_put_page_callback __read_mostly; ++EXPORT_SYMBOL(net_put_page_callback); ++ ++/* ++ * Caller of this function must ensure that at the moment when it's called ++ * there are no pages in the system with net_priv field set to non-zero ++ * value. Hence, this function, as well as net_get_page() and net_put_page(), ++ * don't need any protection. ++ */ ++int net_set_get_put_page_callbacks( ++ net_get_page_callback_t get_callback, ++ net_put_page_callback_t put_callback) ++{ ++ int res = 0; ++ ++ if ((net_get_page_callback != NULL) && (get_callback != NULL) && ++ (net_get_page_callback != get_callback)) { ++ res = -EBUSY; ++ goto out; ++ } ++ ++ if ((net_put_page_callback != NULL) && (put_callback != NULL) && ++ (net_put_page_callback != put_callback)) { ++ res = -EBUSY; ++ goto out; ++ } ++ ++ net_get_page_callback = get_callback; ++ net_put_page_callback = put_callback; ++ ++out: ++ return res; ++} ++EXPORT_SYMBOL(net_set_get_put_page_callbacks); +diff -upkr linux-2.6.29/net/ipv6/ip6_output.c linux-2.6.29/net/ipv6/ip6_output.c +--- linux-2.6.29/net/ipv6/ip6_output.c 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/ipv6/ip6_output.c 2009-03-25 12:13:18.000000000 +0300 +@@ -1394,7 +1394,7 @@ alloc_new_skb: + err = -EMSGSIZE; + goto error; + } +- get_page(page); ++ net_get_page(page); + skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); + frag = &skb_shinfo(skb)->frags[i]; + } +diff -upkr linux-2.6.29/net/Kconfig linux-2.6.29/net/Kconfig +--- linux-2.6.29/net/Kconfig 2009-03-24 02:12:14.000000000 +0300 ++++ linux-2.6.29/net/Kconfig 2009-03-25 12:13:18.000000000 +0300 +@@ -54,6 +54,18 @@ config INET + + Short answer: say Y. + ++config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION ++ bool "TCP/IP zero-copy transfer completion notification" ++ depends on INET ++ default SCST_ISCSI ++ ---help--- ++ Adds support for sending a notification upon completion of a ++ zero-copy TCP/IP transfer. This can speed up certain TCP/IP ++ software. Currently this is only used by the iSCSI target driver ++ iSCSI-SCST. ++ ++ If unsure, say N. ++ + if INET + source "net/ipv4/Kconfig" + source "net/ipv6/Kconfig" diff --git a/iscsi-scst/kernel/session.c b/iscsi-scst/kernel/session.c index 39fba5f0d..39e05c618 100644 --- a/iscsi-scst/kernel/session.c +++ b/iscsi-scst/kernel/session.c @@ -286,7 +286,7 @@ static int iscsi_session_seq_open(struct inode *inode, struct file *file) return res; } -struct file_operations session_seq_fops = { +const struct file_operations session_seq_fops = { .owner = THIS_MODULE, .open = iscsi_session_seq_open, .read = seq_read, diff --git a/iscsi-scst/kernel/target.c b/iscsi-scst/kernel/target.c index a6d8dd362..eaa9e426f 100644 --- a/iscsi-scst/kernel/target.c +++ b/iscsi-scst/kernel/target.c @@ -330,7 +330,7 @@ static int iscsi_seq_show(struct seq_file *m, void *p) return 0; } -struct seq_operations iscsi_seq_op = { +const struct seq_operations iscsi_seq_op = { .start = iscsi_seq_start, .next = iscsi_seq_next, .stop = iscsi_seq_stop, diff --git a/scst/include/scst.h b/scst/include/scst.h index f5c7386de..5af7f4555 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2755,7 +2755,7 @@ int scst_proc_log_entry_write(struct file *file, const char __user *buf, * helper data structure and function to create proc entry. */ struct scst_proc_data { - struct file_operations seq_op; + const struct file_operations seq_op; int (*show)(struct seq_file *, void *); void *data; }; diff --git a/scst/kernel/in-tree/Kconfig.drivers.Linux-2.6.18.patch b/scst/kernel/in-tree/Kconfig.drivers.Linux-2.6.18.patch new file mode 100644 index 000000000..f6ed08886 --- /dev/null +++ b/scst/kernel/in-tree/Kconfig.drivers.Linux-2.6.18.patch @@ -0,0 +1,12 @@ +diff -uprN ../orig/linux-2.6.24/drivers/Kconfig linux-2.6.24/drivers/Kconfig +--- ../orig/linux-2.6.24/drivers/Kconfig 2008-01-24 23:58:37.000000000 +0100 ++++ linux-2.6.24/drivers/Kconfig 2008-05-13 13:05:55.000000000 +0200 +@@ -18,6 +18,8 @@ + + source "drivers/scsi/Kconfig" + ++source "drivers/scst/Kconfig" ++ + source "drivers/cdrom/Kconfig" + + source "drivers/md/Kconfig" diff --git a/scst/kernel/in-tree/Kconfig.drivers.Linux-2.6.29.patch b/scst/kernel/in-tree/Kconfig.drivers.Linux-2.6.29.patch new file mode 100644 index 000000000..81fc97ea1 --- /dev/null +++ b/scst/kernel/in-tree/Kconfig.drivers.Linux-2.6.29.patch @@ -0,0 +1,12 @@ +diff -upkr -X linux-2.6.29/Documentation/dontdiff linux-2.6.29/drivers/Kconfig linux-2.6.29/drivers/Kconfig +--- linux-2.6.29/drivers/Kconfig 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.29/drivers/Kconfig 2008-07-24 14:14:46.000000000 +0400 +@@ -24,6 +24,8 @@ source "drivers/ide/Kconfig" + + source "drivers/scsi/Kconfig" + ++source "drivers/scst/Kconfig" ++ + source "drivers/ata/Kconfig" + + source "drivers/md/Kconfig" diff --git a/scst/kernel/in-tree/Makefile.drivers.Linux-2.6.18.patch b/scst/kernel/in-tree/Makefile.drivers.Linux-2.6.18.patch new file mode 100644 index 000000000..12015a9de --- /dev/null +++ b/scst/kernel/in-tree/Makefile.drivers.Linux-2.6.18.patch @@ -0,0 +1,11 @@ +diff -uprN ../orig/linux-2.6.24/drivers/Makefile linux-2.6.24/drivers/Makefile +--- ../orig/linux-2.6.24/drivers/Makefile 2008-01-24 23:58:37.000000000 +0100 ++++ linux-2.6.24/drivers/Makefile 2008-05-13 13:06:34.000000000 +0200 +@@ -34,6 +34,7 @@ + obj-$(CONFIG_IDE) += ide/ + obj-$(CONFIG_FC4) += fc4/ + obj-$(CONFIG_SCSI) += scsi/ ++obj-$(CONFIG_SCST) += scst/ + obj-$(CONFIG_FUSION) += message/ + obj-$(CONFIG_IEEE1394) += ieee1394/ + obj-y += cdrom/ diff --git a/scst/kernel/in-tree/Makefile.drivers.Linux-2.6.29.patch b/scst/kernel/in-tree/Makefile.drivers.Linux-2.6.29.patch new file mode 100644 index 000000000..eb2defed4 --- /dev/null +++ b/scst/kernel/in-tree/Makefile.drivers.Linux-2.6.29.patch @@ -0,0 +1,11 @@ +diff -upkr -X linux-2.6.29/Documentation/dontdiff linux-2.6.29/drivers/Makefile linux-2.6.29/drivers/Makefile +--- linux-2.6.29/drivers/Makefile 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.29/drivers/Makefile 2008-07-24 14:15:29.000000000 +0400 +@@ -42,6 +42,7 @@ obj-$(CONFIG_ATM) += atm/ + obj-y += macintosh/ + obj-$(CONFIG_IDE) += ide/ + obj-$(CONFIG_SCSI) += scsi/ ++obj-$(CONFIG_SCST) += scst/ + obj-$(CONFIG_ATA) += ata/ + obj-$(CONFIG_FUSION) += message/ + obj-$(CONFIG_FIREWIRE) += firewire/ diff --git a/scst/kernel/io_context-2.6.29.patch b/scst/kernel/io_context-2.6.29.patch new file mode 100644 index 000000000..830b7fba4 --- /dev/null +++ b/scst/kernel/io_context-2.6.29.patch @@ -0,0 +1,61 @@ +diff -upkr linux-2.6.29/block/blk-ioc.c linux-2.6.29/block/blk-ioc.c +--- linux-2.6.29/block/blk-ioc.c 2008-12-25 02:26:37.000000000 +0300 ++++ linux-2.6.29/block/blk-ioc.c 2009-03-23 14:28:48.000000000 +0300 +@@ -65,6 +65,21 @@ static void cfq_exit(struct io_context * + rcu_read_unlock(); + } + ++void __exit_io_context(struct io_context *ioc) ++{ ++ if (ioc == NULL) ++ return; ++ ++ if (atomic_dec_and_test(&ioc->nr_tasks)) { ++ if (ioc->aic && ioc->aic->exit) ++ ioc->aic->exit(ioc->aic); ++ cfq_exit(ioc); ++ ++ put_io_context(ioc); ++ } ++} ++EXPORT_SYMBOL(__exit_io_context); ++ + /* Called by the exitting task */ + void exit_io_context(void) + { +@@ -75,13 +90,7 @@ void exit_io_context(void) + current->io_context = NULL; + task_unlock(current); + +- if (atomic_dec_and_test(&ioc->nr_tasks)) { +- if (ioc->aic && ioc->aic->exit) +- ioc->aic->exit(ioc->aic); +- cfq_exit(ioc); +- +- put_io_context(ioc); +- } ++ __exit_io_context(ioc); + } + + struct io_context *alloc_io_context(gfp_t gfp_flags, int node) +@@ -105,6 +114,7 @@ struct io_context *alloc_io_context(gfp_ + + return ret; + } ++EXPORT_SYMBOL(alloc_io_context); + + /* + * If the current task has no IO context then create one and initialise it. +diff -upkr linux-2.6.29/include/linux/iocontext.h linux-2.6.29/include/linux/iocontext.h +--- linux-2.6.29/include/linux/iocontext.h 2008-12-25 02:26:37.000000000 +0300 ++++ linux-2.6.29/include/linux/iocontext.h 2009-03-23 14:05:01.000000000 +0300 +@@ -103,7 +103,9 @@ static inline struct io_context *ioc_tas + int put_io_context(struct io_context *ioc); + void exit_io_context(void); + struct io_context *get_io_context(gfp_t gfp_flags, int node); ++#define SCST_IO_CONTEXT + struct io_context *alloc_io_context(gfp_t gfp_flags, int node); ++void __exit_io_context(struct io_context *ioc); + void copy_io_context(struct io_context **pdst, struct io_context **psrc); + #else + static inline void exit_io_context(void) diff --git a/scst/kernel/scst_exec_req_fifo-2.6.29.patch b/scst/kernel/scst_exec_req_fifo-2.6.29.patch new file mode 100644 index 000000000..ceb771e22 --- /dev/null +++ b/scst/kernel/scst_exec_req_fifo-2.6.29.patch @@ -0,0 +1,112 @@ +diff -upr linux-2.6.29/drivers/scsi/scsi_lib.c linux-2.6.29/drivers/scsi/scsi_lib.c +--- linux-2.6.29/drivers/scsi/scsi_lib.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.29/drivers/scsi/scsi_lib.c 2008-07-31 21:20:00.000000000 +0400 +@@ -402,7 +402,7 @@ free_bios: + } + + /** +- * scsi_execute_async - insert request ++ * __scsi_execute_async - insert request + * @sdev: scsi device + * @cmd: scsi command + * @cmd_len: length of scsi cdb +@@ -415,11 +415,14 @@ free_bios: + * @privdata: data passed to done() + * @done: callback function when done + * @gfp: memory allocation flags ++ * @at_head: insert request at head or tail of queue + */ +-int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, ++static inline int __scsi_execute_async(struct scsi_device *sdev, ++ const unsigned char *cmd, + int cmd_len, int data_direction, void *buffer, unsigned bufflen, + int use_sg, int timeout, int retries, void *privdata, +- void (*done)(void *, char *, int, int), gfp_t gfp) ++ void (*done)(void *, char *, int, int), gfp_t gfp, ++ int at_head) + { + struct request *req; + struct scsi_io_context *sioc; +@@ -456,7 +461,7 @@ int scsi_execute_async(struct scsi_devic + sioc->data = privdata; + sioc->done = done; + +- blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async); ++ blk_execute_rq_nowait(req->q, NULL, req, at_head, scsi_end_async); + return 0; + + free_req: +@@ -465,8 +468,55 @@ free_sense: + kmem_cache_free(scsi_io_context_cache, sioc); + return DRIVER_ERROR << 24; + } ++ ++/** ++ * scsi_execute_async - insert request ++ * @sdev: scsi device ++ * @cmd: scsi command ++ * @cmd_len: length of scsi cdb ++ * @data_direction: data direction ++ * @buffer: data buffer (this can be a kernel buffer or scatterlist) ++ * @bufflen: len of buffer ++ * @use_sg: if buffer is a scatterlist this is the number of elements ++ * @timeout: request timeout in seconds ++ * @retries: number of times to retry request ++ * @flags: or into request flags ++ **/ ++int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, ++ int cmd_len, int data_direction, void *buffer, ++ unsigned bufflen, int use_sg, int timeout, ++ int retries, void *privdata, ++ void (*done)(void *, char *, int, int), gfp_t gfp) ++{ ++ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, ++ bufflen, use_sg, timeout, retries, privdata, done, gfp, 1); ++} + EXPORT_SYMBOL_GPL(scsi_execute_async); + ++/** ++ * scsi_execute_async_fifo - insert request at tail, in FIFO order ++ * @sdev: scsi device ++ * @cmd: scsi command ++ * @cmd_len: length of scsi cdb ++ * @data_direction: data direction ++ * @buffer: data buffer (this can be a kernel buffer or scatterlist) ++ * @bufflen: len of buffer ++ * @use_sg: if buffer is a scatterlist this is the number of elements ++ * @timeout: request timeout in seconds ++ * @retries: number of times to retry request ++ * @flags: or into request flags ++ **/ ++int scsi_execute_async_fifo(struct scsi_device *sdev, const unsigned char *cmd, ++ int cmd_len, int data_direction, void *buffer, ++ unsigned bufflen, int use_sg, int timeout, int retries, ++ void *privdata, ++ void (*done)(void *, char *, int, int), gfp_t gfp) ++{ ++ return __scsi_execute_async(sdev, cmd, cmd_len, data_direction, buffer, ++ bufflen, use_sg, timeout, retries, privdata, done, gfp, 0); ++} ++EXPORT_SYMBOL_GPL(scsi_execute_async_fifo); ++ + /* + * Function: scsi_init_cmd_errh() + * +diff -upr linux-2.6.29/include/scsi/scsi_device.h linux-2.6.29/include/scsi/scsi_device.h +--- linux-2.6.29/include/scsi/scsi_device.h 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.29/include/scsi/scsi_device.h 2008-07-31 21:20:39.000000000 +0400 +@@ -376,6 +376,14 @@ extern int scsi_execute_async(struct scs + int timeout, int retries, void *privdata, + void (*done)(void *, char *, int, int), + gfp_t gfp); ++#define SCSI_EXEC_REQ_FIFO_DEFINED ++extern int scsi_execute_async_fifo(struct scsi_device *sdev, ++ const unsigned char *cmd, int cmd_len, ++ int data_direction, void *buffer, ++ unsigned bufflen, int use_sg, ++ int timeout, int retries, void *privdata, ++ void (*done)(void *, char *, int, int), ++ gfp_t gfp); + + static inline int __must_check scsi_device_reprobe(struct scsi_device *sdev) + { diff --git a/scst/src/dev_handlers/scst_cdrom.c b/scst/src/dev_handlers/scst_cdrom.c index cc5e2a58a..460ee9ce5 100644 --- a/scst/src/dev_handlers/scst_cdrom.c +++ b/scst/src/dev_handlers/scst_cdrom.c @@ -109,7 +109,11 @@ static int cdrom_attach(struct scst_device *dev) TRACE_DBG("%s", "Doing READ_CAPACITY"); res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer, buffer_size, sense_buffer, - SCST_GENERIC_CDROM_REG_TIMEOUT, 3, 0); + SCST_GENERIC_CDROM_REG_TIMEOUT, 3, 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + , NULL +#endif + ); TRACE_DBG("READ_CAPACITY done: %x", res); diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c index 2257bf673..ddb850c06 100644 --- a/scst/src/dev_handlers/scst_disk.c +++ b/scst/src/dev_handlers/scst_disk.c @@ -185,7 +185,11 @@ static int disk_attach(struct scst_device *dev) TRACE_DBG("%s", "Doing READ_CAPACITY"); res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer, buffer_size, sense_buffer, - SCST_GENERIC_DISK_REG_TIMEOUT, 3, 0); + SCST_GENERIC_DISK_REG_TIMEOUT, 3, 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + , NULL +#endif + ); TRACE_DBG("READ_CAPACITY done: %x", res); diff --git a/scst/src/dev_handlers/scst_modisk.c b/scst/src/dev_handlers/scst_modisk.c index 793743b91..1a45eba02 100644 --- a/scst/src/dev_handlers/scst_modisk.c +++ b/scst/src/dev_handlers/scst_modisk.c @@ -199,7 +199,11 @@ static int modisk_attach(struct scst_device *dev) TRACE_DBG("%s", "Doing READ_CAPACITY"); res = scsi_execute(dev->scsi_dev, cmd, data_dir, buffer, buffer_size, sense_buffer, - SCST_GENERIC_MODISK_REG_TIMEOUT, 3, 0); + SCST_GENERIC_MODISK_REG_TIMEOUT, 3, 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + , NULL +#endif + ); TRACE_DBG("READ_CAPACITY done: %x", res); diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 842c14ccf..601f363e9 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -205,7 +205,7 @@ static struct kmem_cache *user_get_cmd_cachep; static DEFINE_MUTEX(dev_priv_mutex); -static struct file_operations dev_user_fops = { +static const struct file_operations dev_user_fops = { .poll = dev_user_poll, .unlocked_ioctl = dev_user_ioctl, #ifdef CONFIG_COMPAT diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 6cd562ff6..b99aaa9ff 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -3267,7 +3267,7 @@ static int vcdrom_change(char *p, char *name) { loff_t err; struct scst_vdisk_dev *virt_dev, *vv; - char *file_name, *fn, *old_fn; + char *file_name, *fn = NULL, *old_fn; int len; int res = 0; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 51c405344..6d8a1c1bb 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -1664,7 +1664,11 @@ static void scst_send_release(struct scst_device *dev) TRACE(TRACE_DEBUG | TRACE_SCSI, "%s", "Sending RELEASE req to " "SCSI mid-level"); rc = scsi_execute(scsi_dev, cdb, SCST_DATA_NONE, NULL, 0, - sense, 15, 0, 0); + sense, 15, 0, 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + , NULL +#endif + ); TRACE_DBG("MODE_SENSE done: %x", rc); if (scsi_status_is_good(rc)) { @@ -3093,7 +3097,11 @@ int scst_obtain_device_parameters(struct scst_device *dev) TRACE(TRACE_SCSI, "%s", "Doing internal MODE_SENSE"); res = scsi_execute(dev->scsi_dev, cmd, SCST_DATA_READ, buffer, - sizeof(buffer), sense_buffer, 15, 0, 0); + sizeof(buffer), sense_buffer, 15, 0, 0 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + , NULL +#endif + ); TRACE_DBG("MODE_SENSE done: %x", res); @@ -3139,14 +3147,14 @@ int scst_obtain_device_parameters(struct scst_device *dev) } else { #if 0 if ((status_byte(res) == CHECK_CONDITION) && + SCST_SENSE_VALID(sense_buffer)) { #else /* * 3ware controller is buggy and returns CONDITION_GOOD * instead of CHECK_CONDITION */ - if ( + if (SCST_SENSE_VALID(sense_buffer)) { #endif - SCST_SENSE_VALID(sense_buffer)) { if (scst_analyze_sense(sense_buffer, sizeof(sense_buffer), SCST_SENSE_KEY_VALID,