From 20a36529b9f9d4c00841747e4ff46c1dee7d2f35 Mon Sep 17 00:00:00 2001 From: Yan Burman Date: Wed, 28 Jan 2015 09:11:06 +0000 Subject: [PATCH] Merged revisions 5906-5909,5911,5915-5927,5930 via svnmerge from svn+ssh://yanb123@svn.code.sf.net/p/scst/svn/branches/3.0.x ........ r5906 | bvassche | 2014-12-03 19:12:20 +0200 (Wed, 03 Dec 2014) | 1 line Update for kernel 3.17 (merge r5882 from trunk) ........ r5907 | bvassche | 2014-12-03 19:13:06 +0200 (Wed, 03 Dec 2014) | 1 line Add kernel 3.17 build infrastructure (merge r5883 from trunk) ........ r5908 | bvassche | 2014-12-03 19:14:42 +0200 (Wed, 03 Dec 2014) | 1 line scripts: Merge 5827:5907 from trunk ........ r5909 | bvassche | 2014-12-03 19:41:09 +0200 (Wed, 03 Dec 2014) | 1 line Build fixes for RHEL 6.6 kernel 2.6.32-504 (merge r5908 from trunk) ........ r5911 | bvassche | 2014-12-04 14:14:44 +0200 (Thu, 04 Dec 2014) | 1 line scripts/generate-kernel-patch: Swap two filters (merge r5910 from trunk) ........ r5915 | bvassche | 2014-12-05 12:01:49 +0200 (Fri, 05 Dec 2014) | 1 line iscsi-scst/kernel/patches/rhel/put_page_callback-2.6.32-504.patch: Add (merge r5904 from trunk) ........ r5916 | bvassche | 2014-12-05 12:22:05 +0200 (Fri, 05 Dec 2014) | 1 line nightly: Merge r5720:5915 from trunk ........ r5917 | bvassche | 2014-12-05 12:30:54 +0200 (Fri, 05 Dec 2014) | 1 line scst_lib: Fix READ POSITION parsing (merge r5740 from trunk) ........ r5918 | bvassche | 2014-12-05 12:33:22 +0200 (Fri, 05 Dec 2014) | 1 line scst: Clean up __scst_resume_activity() (merge r5589 from trunk) ........ r5919 | bvassche | 2014-12-05 12:49:20 +0200 (Fri, 05 Dec 2014) | 1 line scstadmin regression tests: Merge r5475:5915 from trunk ........ r5920 | bvassche | 2014-12-05 12:50:41 +0200 (Fri, 05 Dec 2014) | 1 line scstadmin: Sync saved configuration files (merge r5793 from trunk) ........ r5921 | bvassche | 2014-12-05 12:57:03 +0200 (Fri, 05 Dec 2014) | 1 line ib_srpt: Speed up kernel driver unloading after a cable pull (merge r5727 from trunk) ........ r5922 | bvassche | 2014-12-05 14:24:23 +0200 (Fri, 05 Dec 2014) | 1 line scst_local: Avoid that session deletion triggers a kernel warning (merge r5601 and 5631 from trunk) ........ r5923 | bvassche | 2014-12-05 14:25:46 +0200 (Fri, 05 Dec 2014) | 1 line scst_local: Set max_id to 1 (merge r5786 from trunk) ........ r5924 | bvassche | 2014-12-05 14:55:32 +0200 (Fri, 05 Dec 2014) | 1 line scst: Add 64-bit LUN support (kernel 3.17 - merge r5587 from trunk) ........ r5925 | bvassche | 2014-12-05 14:56:59 +0200 (Fri, 05 Dec 2014) | 1 line scst_local: Add 64-bit LUN support (kernel 3.17 - merge r5588 from trunk) ........ r5926 | bvassche | 2014-12-05 14:59:32 +0200 (Fri, 05 Dec 2014) | 1 line scst: Remove unused variables (merge r5585 from trunk) ........ r5927 | bvassche | 2014-12-05 15:01:57 +0200 (Fri, 05 Dec 2014) | 1 line scst: Avoid complaints about unused variables (merge r5600 from trunk) ........ r5930 | bvassche | 2014-12-09 14:34:50 +0200 (Tue, 09 Dec 2014) | 1 line rpm build: Add support for qla2x00t driver in QLogic git repository (merge r5929 from trunk) ........ git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.0.x-iser@5992 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- Makefile | 8 +- fcst/ft_sess.c | 4 +- .../patches/put_page_callback-3.17.patch | 364 ++++++++++++ .../rhel/put_page_callback-2.6.32-504.patch | 453 +++++++++++++++ nightly/conf/nightly.conf | 9 +- qla2x00t/qla2x00-target/Makefile_in-tree-3.17 | 5 + qla2x00t/qla_isr.c | 50 +- qla2x00t/qla_os.c | 20 +- scripts/generate-kernel-patch | 12 +- scripts/generate-release-archive | 12 +- scripts/rebuild-rhel-kernel-rpm | 38 +- scripts/specialize-patch | 10 +- .../in-tree/Kconfig.drivers.Linux-3.17.patch | 13 + .../kernel/in-tree/Makefile.dev_handlers-3.17 | 14 + .../in-tree/Makefile.drivers.Linux-3.17.patch | 12 + scst/kernel/in-tree/Makefile.scst-3.17 | 13 + scst/kernel/scst_exec_req_fifo-3.17.patch | 524 ++++++++++++++++++ scst/src/dev_handlers/scst_tape.c | 6 +- scst/src/dev_handlers/scst_vdisk.c | 3 +- scst/src/scst_lib.c | 7 +- scst/src/scst_main.c | 34 +- scst/src/scst_pres.c | 7 +- scst/src/scst_sysfs.c | 15 +- scst/src/scst_targ.c | 2 + scst_local/in-tree/Makefile-3.17 | 2 + scst_local/scst_local.c | 101 +++- .../scst-0.9.10/t/06-cont-on-err.t | 2 +- .../scst-0.9.10/t/after-restore.conf | 2 +- .../scst-0.9.10/t/to-be-restored.conf | 2 +- scstadmin/scstadmin.sysfs/scstadmin | 2 + srpt/patches/kernel-3.17-pre-cflags.patch | 12 + srpt/src/ib_srpt.c | 11 +- 32 files changed, 1648 insertions(+), 121 deletions(-) create mode 100644 iscsi-scst/kernel/patches/put_page_callback-3.17.patch create mode 100644 iscsi-scst/kernel/patches/rhel/put_page_callback-2.6.32-504.patch create mode 100644 qla2x00t/qla2x00-target/Makefile_in-tree-3.17 create mode 100644 scst/kernel/in-tree/Kconfig.drivers.Linux-3.17.patch create mode 100644 scst/kernel/in-tree/Makefile.dev_handlers-3.17 create mode 100644 scst/kernel/in-tree/Makefile.drivers.Linux-3.17.patch create mode 100644 scst/kernel/in-tree/Makefile.scst-3.17 create mode 100644 scst/kernel/scst_exec_req_fifo-3.17.patch create mode 100644 scst_local/in-tree/Makefile-3.17 create mode 100644 srpt/patches/kernel-3.17-pre-cflags.patch diff --git a/Makefile b/Makefile index c85d9f619..a068a0c0a 100644 --- a/Makefile +++ b/Makefile @@ -376,7 +376,13 @@ fcst_extraclean: scst-dist-gzip: name=scst && \ mkdir $${name}-$(VERSION) && \ - { scripts/list-source-files | \ + { if [ -h qla2x00t ] || { mount | grep "on $$PWD/qla2x00t type"; }; \ + then \ + scripts/list-source-files | grep -v ^qla2x00t/; \ + find qla2x00t/ -type f; \ + else \ + scripts/list-source-files; \ + fi | \ grep -E '^doc/|^fcst/|^iscsi-scst/|^Makefile|^qla2x00t/|^scst.spec|^scst/|^scst_local/|^srpt/'|\ tar -T- -cf- | \ tar -C $${name}-$(VERSION) -xf-; } && \ diff --git a/fcst/ft_sess.c b/fcst/ft_sess.c index 1690a87d1..81caf8bae 100644 --- a/fcst/ft_sess.c +++ b/fcst/ft_sess.c @@ -181,7 +181,9 @@ static u32 ft_sess_hash(u32 port_id) LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 41)) && \ ! (LINUX_VERSION_CODE >> 8 == KERNEL_VERSION(3, 2, 0) >> 8 && \ LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 44)) && \ - !defined(CONFIG_SUSE_KERNEL) + !defined(CONFIG_SUSE_KERNEL) && \ + (!defined(RHEL_MAJOR) || RHEL_MAJOR -0 < 6 || \ + (RHEL_MAJOR -0 == 6 && RHEL_MINOR -0 < 6)) /* * See also commit 4b20db3 (kref: Implement kref_get_unless_zero v3 -- v3.8). * See also commit e3a5505 in branch stable/linux-3.4.y (v3.4.41). diff --git a/iscsi-scst/kernel/patches/put_page_callback-3.17.patch b/iscsi-scst/kernel/patches/put_page_callback-3.17.patch new file mode 100644 index 000000000..b049270ea --- /dev/null +++ b/iscsi-scst/kernel/patches/put_page_callback-3.17.patch @@ -0,0 +1,364 @@ +=== modified file 'drivers/block/drbd/drbd_receiver.c' +--- old/drivers/block/drbd/drbd_receiver.c 2014-11-21 03:17:49 +0000 ++++ new/drivers/block/drbd/drbd_receiver.c 2014-11-21 03:51:00 +0000 +@@ -132,7 +132,7 @@ static int page_chain_free(struct page * + struct page *tmp; + int i = 0; + page_chain_for_each_safe(page, tmp) { +- put_page(page); ++ net_put_page(page); + ++i; + } + return i; + +=== modified file 'include/linux/mm_types.h' +--- old/include/linux/mm_types.h 2014-11-21 03:17:49 +0000 ++++ new/include/linux/mm_types.h 2014-11-21 03:51:00 +0000 +@@ -196,6 +196,17 @@ struct page { + #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS + int _last_cpupid; + #endif ++ ++#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 + } + /* + * The struct page can be forced to be double word aligned so that atomic ops + +=== modified file 'include/linux/net.h' +--- old/include/linux/net.h 2014-11-21 03:17:49 +0000 ++++ new/include/linux/net.h 2014-11-21 03:51:00 +0000 +@@ -19,6 +19,7 @@ + #define _LINUX_NET_H + + #include ++#include + #include + #include + #include /* For O_CLOEXEC and O_NONBLOCK */ +@@ -285,6 +286,45 @@ int kernel_sendpage(struct socket *sock, + int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); + int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how); + ++#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 */ ++ + #define MODULE_ALIAS_NETPROTO(proto) \ + MODULE_ALIAS("net-pf-" __stringify(proto)) + + +=== modified file 'include/linux/skbuff.h' +--- old/include/linux/skbuff.h 2014-11-21 03:17:49 +0000 ++++ new/include/linux/skbuff.h 2014-11-21 03:51:00 +0000 +@@ -2145,7 +2145,7 @@ static inline struct page *skb_frag_page + */ + static inline void __skb_frag_ref(skb_frag_t *frag) + { +- get_page(skb_frag_page(frag)); ++ net_get_page(skb_frag_page(frag)); + } + + /** +@@ -2168,7 +2168,7 @@ static inline void skb_frag_ref(struct s + */ + static inline void __skb_frag_unref(skb_frag_t *frag) + { +- put_page(skb_frag_page(frag)); ++ net_put_page(skb_frag_page(frag)); + } + + /** + +=== modified file 'net/Kconfig' +--- old/net/Kconfig 2014-11-21 03:17:49 +0000 ++++ new/net/Kconfig 2014-11-21 03:51:00 +0000 +@@ -75,6 +75,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" + +=== modified file 'net/ceph/pagevec.c' +--- old/net/ceph/pagevec.c 2014-11-21 03:17:49 +0000 ++++ new/net/ceph/pagevec.c 2014-11-21 03:51:00 +0000 +@@ -51,7 +51,7 @@ void ceph_put_page_vector(struct page ** + for (i = 0; i < num_pages; i++) { + if (dirty) + set_page_dirty_lock(pages[i]); +- put_page(pages[i]); ++ net_put_page(pages[i]); + } + if (is_vmalloc_addr(pages)) + vfree(pages); + +=== modified file 'net/core/skbuff.c' +--- old/net/core/skbuff.c 2014-11-21 03:17:49 +0000 ++++ new/net/core/skbuff.c 2014-11-21 03:51:00 +0000 +@@ -426,7 +426,7 @@ struct sk_buff *__netdev_alloc_skb(struc + if (likely(data)) { + skb = build_skb(data, fragsz); + if (unlikely(!skb)) +- put_page(virt_to_head_page(data)); ++ net_put_page(virt_to_head_page(data)); + } + } else { + skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, +@@ -484,7 +484,7 @@ static void skb_clone_fraglist(struct sk + static void skb_free_head(struct sk_buff *skb) + { + if (skb->head_frag) +- put_page(virt_to_head_page(skb->head)); ++ net_put_page(virt_to_head_page(skb->head)); + else + kfree(skb->head); + } +@@ -808,7 +808,7 @@ int skb_copy_ubufs(struct sk_buff *skb, + if (!page) { + while (head) { + struct page *next = (struct page *)page_private(head); +- put_page(head); ++ net_put_page(head); + head = next; + } + return -ENOMEM; +@@ -1655,7 +1655,7 @@ EXPORT_SYMBOL(skb_copy_bits); + */ + 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 struct page *linear_to_page(struct page *page, unsigned int *len, +@@ -1708,7 +1708,7 @@ static bool spd_fill_page(struct splice_ + spd->partial[spd->nr_pages - 1].len += *len; + return false; + } +- get_page(page); ++ net_get_page(page); + spd->pages[spd->nr_pages] = page; + spd->partial[spd->nr_pages].len = *len; + spd->partial[spd->nr_pages].offset = offset; +@@ -2167,7 +2167,7 @@ skb_zerocopy(struct sk_buff *to, struct + page = virt_to_head_page(from->head); + offset = from->data - (unsigned char *)page_address(page); + __skb_fill_page_desc(to, 0, page, offset, plen); +- get_page(page); ++ net_get_page(page); + j = 1; + len -= plen; + } +@@ -2821,7 +2821,7 @@ int skb_append_datato_frags(struct sock + copy); + frg_cnt++; + pfrag->offset += copy; +- get_page(pfrag->page); ++ net_get_page(pfrag->page); + + skb->truesize += copy; + atomic_add(copy, &sk->sk_wmem_alloc); + +=== modified file 'net/core/sock.c' +--- old/net/core/sock.c 2014-11-21 03:17:49 +0000 ++++ new/net/core/sock.c 2014-11-21 03:51:00 +0000 +@@ -1881,7 +1881,7 @@ bool skb_page_frag_refill(unsigned int s + } + if (pfrag->offset + sz <= pfrag->size) + return true; +- put_page(pfrag->page); ++ net_put_page(pfrag->page); + } + + pfrag->offset = 0; +@@ -2645,7 +2645,7 @@ void sk_common_release(struct sock *sk) + sk_refcnt_debug_release(sk); + + if (sk->sk_frag.page) { +- put_page(sk->sk_frag.page); ++ net_put_page(sk->sk_frag.page); + sk->sk_frag.page = NULL; + } + + +=== modified file 'net/ipv4/Makefile' +--- old/net/ipv4/Makefile 2014-11-21 03:17:49 +0000 ++++ new/net/ipv4/Makefile 2014-11-21 03:51:00 +0000 +@@ -54,6 +54,7 @@ obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah. + obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o + obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.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 xfrm4_protocol.o + +=== modified file 'net/ipv4/ip_output.c' +--- old/net/ipv4/ip_output.c 2014-11-21 03:17:49 +0000 ++++ new/net/ipv4/ip_output.c 2014-11-21 03:51:00 +0000 +@@ -1051,7 +1051,7 @@ alloc_new_skb: + __skb_fill_page_desc(skb, i, pfrag->page, + pfrag->offset, 0); + skb_shinfo(skb)->nr_frags = ++i; +- get_page(pfrag->page); ++ net_get_page(pfrag->page); + } + copy = min_t(int, copy, pfrag->size - pfrag->offset); + if (getfrag(from, +@@ -1276,7 +1276,7 @@ ssize_t ip_append_page(struct sock *sk, + if (skb_can_coalesce(skb, i, page, offset)) { + skb_frag_size_add(&skb_shinfo(skb)->frags[i-1], 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; + +=== modified file 'net/ipv4/tcp.c' +--- old/net/ipv4/tcp.c 2014-11-21 03:17:49 +0000 ++++ new/net/ipv4/tcp.c 2014-11-21 03:51:00 +0000 +@@ -950,7 +950,7 @@ new_segment: + if (can_coalesce) { + skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); + } else { +- get_page(page); ++ net_get_page(page); + skb_fill_page_desc(skb, i, page, offset, copy); + } + skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; +@@ -1251,7 +1251,7 @@ new_segment: + } else { + skb_fill_page_desc(skb, i, pfrag->page, + pfrag->offset, copy); +- get_page(pfrag->page); ++ net_get_page(pfrag->page); + } + pfrag->offset += copy; + } + +=== added file 'net/ipv4/tcp_zero_copy.c' +--- old/net/ipv4/tcp_zero_copy.c 1970-01-01 00:00:00 +0000 ++++ new/net/ipv4/tcp_zero_copy.c 2014-11-21 03:51:00 +0000 +@@ -0,0 +1,50 @@ ++/* ++ * 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 ++#include ++ ++net_get_page_callback_t net_get_page_callback __read_mostly; ++EXPORT_SYMBOL_GPL(net_get_page_callback); ++ ++net_put_page_callback_t net_put_page_callback __read_mostly; ++EXPORT_SYMBOL_GPL(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_GPL(net_set_get_put_page_callbacks); + +=== modified file 'net/ipv6/ip6_output.c' +--- old/net/ipv6/ip6_output.c 2014-11-21 03:17:49 +0000 ++++ new/net/ipv6/ip6_output.c 2014-11-21 03:51:00 +0000 +@@ -1477,7 +1477,7 @@ alloc_new_skb: + __skb_fill_page_desc(skb, i, pfrag->page, + pfrag->offset, 0); + skb_shinfo(skb)->nr_frags = ++i; +- get_page(pfrag->page); ++ net_get_page(pfrag->page); + } + copy = min_t(int, copy, pfrag->size - pfrag->offset); + if (getfrag(from, + diff --git a/iscsi-scst/kernel/patches/rhel/put_page_callback-2.6.32-504.patch b/iscsi-scst/kernel/patches/rhel/put_page_callback-2.6.32-504.patch new file mode 100644 index 000000000..5159dd59f --- /dev/null +++ b/iscsi-scst/kernel/patches/rhel/put_page_callback-2.6.32-504.patch @@ -0,0 +1,453 @@ +[PATCH] put_page_callback-2.6.32-504 + +--- + include/linux/Kbuild | 1 + + include/linux/mm_types.h | 12 +++++++++++ + include/linux/net.h | 40 +++++++++++++++++++++++++++++++++++++ + net/Kconfig | 12 +++++++++++ + net/core/dev.c | 2 +- + net/core/skbuff.c | 34 ++++++++++++++++---------------- + net/ipv4/Makefile | 1 + + net/ipv4/ip_output.c | 4 +- + net/ipv4/tcp.c | 8 +++--- + net/ipv4/tcp_output.c | 2 +- + net/ipv4/tcp_zero_copy.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ + net/ipv6/ip6_output.c | 2 +- + 12 files changed, 141 insertions(+), 26 deletions(-) + create mode 100644 net/ipv4/tcp_zero_copy.c + +diff --git a/include/linux/Kbuild b/include/linux/Kbuild +index 9301043..2870f1a 100644 +--- a/include/linux/Kbuild ++++ b/include/linux/Kbuild +@@ -113,6 +113,7 @@ header-y += map_to_7segment.h + header-y += matroxfb.h + header-y += meye.h + header-y += minix_fs.h ++header-y += mm.h + header-y += mmtimer.h + header-y += mqueue.h + header-y += mtio.h +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 645f205..7b6de1f 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -106,6 +106,18 @@ struct page { + */ + void *shadow; + #endif ++ ++#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 --git a/include/linux/net.h b/include/linux/net.h +index 58ada6b..b0adbdc 100644 +--- a/include/linux/net.h ++++ b/include/linux/net.h +@@ -20,6 +20,7 @@ + + #include + #include ++#include + + #define NPROTO AF_MAX + +@@ -389,5 +390,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 --git a/net/Kconfig b/net/Kconfig +index 1d9b405..eedbed6 100644 +--- a/net/Kconfig ++++ b/net/Kconfig +@@ -72,6 +72,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/net/core/dev.c b/net/core/dev.c +index 61dce2f..25d0826 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -3655,7 +3655,7 @@ pull: + skb_shinfo(skb)->frags[0].size -= grow; + + if (unlikely(!skb_shinfo(skb)->frags[0].size)) { +- put_page(skb_shinfo(skb)->frags[0].page); ++ net_put_page(skb_shinfo(skb)->frags[0].page); + memmove(skb_shinfo(skb)->frags, + skb_shinfo(skb)->frags + 1, + --skb_shinfo(skb)->nr_frags); +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 157dc11..74ac749 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -78,13 +78,13 @@ static struct kmem_cache *skbuff_fclone_cache __read_mostly; + 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, +@@ -396,7 +396,7 @@ static void skb_release_data(struct sk_buff *skb) + 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); + } + + /* +@@ -705,7 +705,7 @@ static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) + if (!page) { + while (head) { + struct page *next = (struct page *)head->private; +- put_page(head); ++ net_put_page(head); + head = next; + } + return -ENOMEM; +@@ -720,7 +720,7 @@ static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) + + /* skb frags release userspace buffers */ + 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); + + uarg->callback(uarg); + +@@ -886,7 +886,7 @@ struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask) + } + 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; + } +@@ -967,7 +967,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, + skb_tx(skb)->dev_zerocopy = 0; + } + 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_has_frag_list(skb)) + skb_clone_fraglist(skb); +@@ -1246,7 +1246,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_has_frag_list(skb)) + skb_drop_fraglist(skb); +@@ -1415,7 +1415,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]; +@@ -1517,7 +1517,7 @@ EXPORT_SYMBOL(skb_copy_bits); + */ + 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, +@@ -1541,7 +1541,7 @@ new_page: + off = sk->sk_sndmsg_off; + mlen = PAGE_SIZE - off; + if (mlen < 64 && mlen < *len) { +- put_page(p); ++ net_put_page(p); + goto new_page; + } + +@@ -1551,7 +1551,7 @@ new_page: + memcpy(page_address(p) + off, page_address(page) + *offset, *len); + sk->sk_sndmsg_off += *len; + *offset = off; +- get_page(p); ++ net_get_page(p); + + return p; + } +@@ -1572,7 +1572,7 @@ static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page, + 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; +@@ -2202,7 +2202,7 @@ static inline void skb_split_no_header(struct sk_buff *skb, + * 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; +@@ -2325,7 +2325,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) + to++; + + } else { +- get_page(fragfrom->page); ++ net_get_page(fragfrom->page); + fragto->page = fragfrom->page; + fragto->page_offset = fragfrom->page_offset; + fragto->size = todo; +@@ -2347,7 +2347,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) + fragto = &skb_shinfo(tgt)->frags[merge]; + + fragto->size += fragfrom->size; +- put_page(fragfrom->page); ++ net_put_page(fragfrom->page); + } + + /* Reposition in the original skb */ +@@ -2760,7 +2760,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) + + 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 --git a/net/ipv4/Makefile b/net/ipv4/Makefile +index e18daba..65f5371 100644 +--- a/net/ipv4/Makefile ++++ b/net/ipv4/Makefile +@@ -51,6 +51,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 --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 7ac7cfa..8cda5cc 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1000,7 +1000,7 @@ alloc_new_skb: + err = -EMSGSIZE; + goto error; + } +- get_page(page); ++ net_get_page(page); + skb_fill_page_desc(skb, i, page, off, 0); + frag = &skb_shinfo(skb)->frags[i]; + } +@@ -1239,7 +1239,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, + 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 --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 18d22cf..b5c12fa 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -821,7 +821,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); + } + skb_tx(skb)->shared_frag = 1; +@@ -1030,7 +1030,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; + } +@@ -1071,9 +1071,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 --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 255e6e3..5c48819 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1071,7 +1071,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) + 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 --git a/net/ipv4/tcp_zero_copy.c b/net/ipv4/tcp_zero_copy.c +new file mode 100644 +index 0000000..9cd990c +--- /dev/null ++++ b/net/ipv4/tcp_zero_copy.c +@@ -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 --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 0e985f7..22b4529 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1375,7 +1375,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]; + } +-- +1.7.1 + diff --git a/nightly/conf/nightly.conf b/nightly/conf/nightly.conf index 6e99671ba..43fd6e588 100644 --- a/nightly/conf/nightly.conf +++ b/nightly/conf/nightly.conf @@ -3,13 +3,14 @@ ABT_DETAILS="x86_64" ABT_JOBS=5 ABT_KERNELS=" \ -3.16.1 \ +3.17.4 \ +3.16.7-nc \ 3.15.10-nc \ -3.14.17-nc \ +3.14.25-nc \ 3.13.11-nc \ -3.12.21-nc \ +3.12.33-nc \ 3.11.10-nc \ -3.10.53-nc \ +3.10.61-nc \ 3.9.11-nc \ 3.8.13-nc \ 3.7.10-nc \ diff --git a/qla2x00t/qla2x00-target/Makefile_in-tree-3.17 b/qla2x00t/qla2x00-target/Makefile_in-tree-3.17 new file mode 100644 index 000000000..9657aee84 --- /dev/null +++ b/qla2x00t/qla2x00-target/Makefile_in-tree-3.17 @@ -0,0 +1,5 @@ +ccflags-y += -Idrivers/scsi/qla2xxx + +qla2x00tgt-y := qla2x00t.o + +obj-$(CONFIG_SCST_QLA_TGT_ADDON) += qla2x00tgt.o diff --git a/qla2x00t/qla_isr.c b/qla2x00t/qla_isr.c index 8395186d8..5391b17e4 100644 --- a/qla2x00t/qla_isr.c +++ b/qla2x00t/qla_isr.c @@ -781,8 +781,8 @@ qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data) fcport->last_ramp_up = jiffies; DEBUG2(qla_printk(KERN_INFO, fcport->ha, - "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n", - fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun, + "scsi(%ld:%d:%d:%lld): Queue depth adjusted-up to %d.\n", + fcport->ha->host_no, sdev->channel, sdev->id, (unsigned long long)sdev->lun, sdev->queue_depth)); } @@ -795,8 +795,8 @@ qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data) return; DEBUG2(qla_printk(KERN_INFO, fcport->ha, - "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n", - fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun, + "scsi(%ld:%d:%d:%lld): Queue depth adjusted-down to %d.\n", + fcport->ha->host_no, sdev->channel, sdev->id, (unsigned long long)sdev->lun, sdev->queue_depth)); } @@ -1140,11 +1140,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if (IS_FWI2_CAPABLE(ha)) sense_data += rsp_info_len; if (rsp_info_len > 3 && rsp_info[3]) { - DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " + DEBUG2(printk("scsi(%ld:%d:%d:%lld) FCP I/O protocol " "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." "retrying command\n", ha->host_no, cp->device->channel, cp->device->id, - cp->device->lun, rsp_info_len, rsp_info[0], + (unsigned long long)cp->device->lun, rsp_info_len, rsp_info[0], rsp_info[1], rsp_info[2], rsp_info[3], rsp_info[4], rsp_info[5], rsp_info[6], rsp_info[7])); @@ -1178,11 +1178,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) ((unsigned)(scsi_bufflen(cp) - resid) < cp->underflow)) { qla_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): Mid-layer underflow " + "scsi(%ld:%d:%d:%lld): Mid-layer underflow " "detected (%x of %x bytes)...returning " "error status.\n", ha->host_no, cp->device->channel, cp->device->id, - cp->device->lun, resid, + (unsigned long long)cp->device->lun, resid, scsi_bufflen(cp)); cp->result = DID_ERROR << 16; @@ -1230,10 +1230,10 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) CMD_RESID_LEN(cp) = resid; } else { DEBUG2(printk(KERN_INFO - "scsi(%ld:%d:%d) UNDERRUN status detected " + "scsi(%ld:%d:%lld) UNDERRUN status detected " "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x " "os_underflow=0x%x\n", ha->host_no, - cp->device->id, cp->device->lun, comp_status, + cp->device->id, (unsigned long long)cp->device->lun, comp_status, scsi_status, resid_len, resid, cp->cmnd[0], cp->underflow)); @@ -1277,11 +1277,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) * layer to retry it by reporting a bus busy. */ if (!(scsi_status & SS_RESIDUAL_UNDER)) { - DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " + DEBUG2(printk("scsi(%ld:%d:%d:%lld) Dropped " "frame(s) detected (%x of %x bytes)..." "retrying command.\n", ha->host_no, cp->device->channel, cp->device->id, - cp->device->lun, resid, + (unsigned long long)cp->device->lun, resid, scsi_bufflen(cp))); cp->result = DID_BUS_BUSY << 16; @@ -1292,11 +1292,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if ((unsigned)(scsi_bufflen(cp) - resid) < cp->underflow) { qla_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): Mid-layer underflow " + "scsi(%ld:%d:%d:%lld): Mid-layer underflow " "detected (%x of %x bytes)...returning " "error status.\n", ha->host_no, cp->device->channel, cp->device->id, - cp->device->lun, resid, + (unsigned long long)cp->device->lun, resid, scsi_bufflen(cp)); cp->result = DID_ERROR << 16; @@ -1310,9 +1310,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) case CS_DATA_OVERRUN: DEBUG2(printk(KERN_INFO - "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n", - ha->host_no, cp->device->id, cp->device->lun, comp_status, - scsi_status)); + "scsi(%ld:%d:%lld): OVERRUN status detected 0x%x-0x%x\n", + ha->host_no, cp->device->id, (unsigned long long)cp->device->lun, + comp_status, scsi_status)); DEBUG2(printk(KERN_INFO "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3], @@ -1335,9 +1335,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) * Target with DID_NO_CONNECT ELSE Queue the IOs in the * retry_queue. */ - DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " + DEBUG2(printk("scsi(%ld:%d:%lld): status_entry: Port Down " "pid=%ld, compl status=0x%x, port state=0x%x\n", - ha->host_no, cp->device->id, cp->device->lun, + ha->host_no, cp->device->id, (unsigned long long)cp->device->lun, cp->serial_number, comp_status, atomic_read(&fcport->state))); @@ -1373,17 +1373,17 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) if (IS_FWI2_CAPABLE(ha)) { DEBUG2(printk(KERN_INFO - "scsi(%ld:%d:%d:%d): TIMEOUT status detected " + "scsi(%ld:%d:%d:%lld): TIMEOUT status detected " "0x%x-0x%x\n", ha->host_no, cp->device->channel, - cp->device->id, cp->device->lun, comp_status, - scsi_status)); + cp->device->id, (unsigned long long)cp->device->lun, + comp_status, scsi_status)); break; } DEBUG2(printk(KERN_INFO - "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x " + "scsi(%ld:%d:%d:%lld): TIMEOUT status detected 0x%x-0x%x " "sflags=%x.\n", ha->host_no, cp->device->channel, - cp->device->id, cp->device->lun, comp_status, scsi_status, - le16_to_cpu(sts->status_flags))); + cp->device->id, (unsigned long long)cp->device->lun, comp_status, + scsi_status, le16_to_cpu(sts->status_flags))); /* Check to see if logout occurred. */ if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index b2b105615..5c7018eaf 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -909,8 +909,8 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, if (!fcport) return FAILED; - qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET ISSUED.\n", - ha->host_no, cmd->device->id, cmd->device->lun, name); + qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%lld): %s RESET ISSUED.\n", + ha->host_no, cmd->device->id, (unsigned long long)cmd->device->lun, name); err = 0; if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) @@ -926,14 +926,14 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, cmd->device->lun, type) != QLA_SUCCESS) goto eh_reset_failed; - qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET SUCCEEDED.\n", - ha->host_no, cmd->device->id, cmd->device->lun, name); + qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%lld): %s RESET SUCCEEDED.\n", + ha->host_no, cmd->device->id, (unsigned long long)cmd->device->lun, name); return SUCCESS; eh_reset_failed: - qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d): %s RESET FAILED: %s.\n", - ha->host_no, cmd->device->id, cmd->device->lun, name, + qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%lld): %s RESET FAILED: %s.\n", + ha->host_no, cmd->device->id, (unsigned long long)cmd->device->lun, name, reset_errors[err]); return FAILED; } @@ -1228,8 +1228,8 @@ static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth) return; DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n", - ha->host_no, sdev->channel, sdev->id, sdev->lun, + "scsi(%ld:%d:%d:%lld): Queue depth adjusted-down to %d.\n", + ha->host_no, sdev->channel, sdev->id, (unsigned long long)sdev->lun, sdev->queue_depth)); } @@ -1246,8 +1246,8 @@ static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth) scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth); DEBUG2(qla_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n", - ha->host_no, sdev->channel, sdev->id, sdev->lun, + "scsi(%ld:%d:%d:%lld): Queue depth adjusted-up to %d.\n", + ha->host_no, sdev->channel, sdev->id, (unsigned long long)sdev->lun, sdev->queue_depth)); } diff --git a/scripts/generate-kernel-patch b/scripts/generate-kernel-patch index d41d188e9..6c443d974 100755 --- a/scripts/generate-kernel-patch +++ b/scripts/generate-kernel-patch @@ -107,16 +107,16 @@ EOF # passed via stdin and send the specialized patch to stdout. function specialize_patch { if [ "${enable_specialize}" = "true" ]; then + if [ "${generating_upstream_patch}" = "true" ]; then + scripts/filter-trace-entry-exit + else + cat + fi | "$(dirname $0)/specialize-patch" \ ${specialize_patch_options} \ -v kernel_version="${kver3}" \ -v SCSI_EXEC_REQ_FIFO_DEFINED="${scsi_exec_req_fifo_defined}" \ - -v SCST_IO_CONTEXT="${scst_io_context}" \ - | if [ "${generating_upstream_patch}" = "true" ]; then - scripts/filter-trace-entry-exit - else - cat - fi + -v SCST_IO_CONTEXT="${scst_io_context}" else cat fi diff --git a/scripts/generate-release-archive b/scripts/generate-release-archive index 1c4fe2d75..3980ac7dd 100755 --- a/scripts/generate-release-archive +++ b/scripts/generate-release-archive @@ -4,15 +4,19 @@ usage() { echo "Usage: $(basename $0) name version" } -if [ $# != 2 ]; then +if [ $# -lt 2 ]; then usage exit 1 fi scriptdir="$(dirname "$0")" -name="$1" -version="$2" +name="$1"; shift +version="$1"; shift +files="$*" +if [ -z "$files" ]; then + files=$($scriptdir/list-source-files) +fi tar --owner=root --group=root --transform="s|^|$name-$version/|" \ - -cjf $name-$version.tar.bz2 $($scriptdir/list-source-files) && + -cjf $name-$version.tar.bz2 $files && ls -l $name-$version.tar.bz2 diff --git a/scripts/rebuild-rhel-kernel-rpm b/scripts/rebuild-rhel-kernel-rpm index e4a96c1d7..df8569a2f 100755 --- a/scripts/rebuild-rhel-kernel-rpm +++ b/scripts/rebuild-rhel-kernel-rpm @@ -227,7 +227,7 @@ copy_best_matching_patch $scst_dir/scst/kernel/rhel/scst_exec_req_fifo scst_exec } copy_best_matching_patch $scst_dir/iscsi-scst/kernel/patches/rhel/put_page_callback put_page_callback.patch || { - echo "No matching scst_exec_req_fifo patch found for kernel version $kver"; + echo "No matching put_page_callback patch found for kernel version $kver"; exit 1; } @@ -365,6 +365,42 @@ diff -u SPECS/kernel.spec{.orig,} make ARCH=$Arch %{oldconfig_target} > /dev/null echo "# $Arch" > configs/$i EOF +elif [ ${kver#2.6.32-504.} != $kver ]; then +# RHEL/CentOS/SL 6.6 +patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? +diff -u SPECS/kernel.spec{.orig,} +--- kernel.spec.orig 2014-12-03 16:20:14.764118318 +0100 ++++ kernel.spec 2014-12-03 16:21:36.606089530 +0100 +@@ -610,6 +610,9 @@ + Source85: config-powerpc64-debug-rhel + Source86: config-s390x-debug-rhel + ++Patch200: scst_exec_req_fifo.patch ++Patch201: put_page_callback.patch ++ + # empty final patch file to facilitate testing of kernel patches + Patch999999: linux-kernel-test.patch + +@@ -932,6 +935,9 @@ + # Dynamically generate kernel .config files from config-* files + make -f %{SOURCE20} VERSION=%{version} configs + ++ApplyPatch scst_exec_req_fifo.patch ++ApplyPatch put_page_callback.patch ++ + ApplyOptionalPatch linux-kernel-test.patch + + # Any further pre-build tree manipulations happen here. +@@ -958,6 +964,8 @@ + for i in *.config + do + mv $i .config ++ echo "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y" >> .config ++ sed -i.tmp -e 's/^CONFIG_SCSI_QLA_FC=.*/CONFIG_SCSI_QLA_FC=n/' .config + Arch=`head -1 .config | cut -b 3-` + make ARCH=$Arch %{oldconfig_target} > /dev/null + echo "# $Arch" > configs/$i +EOF elif [ ${kver#3.10.0-12[13]} != $kver ]; then # RHEL/CentOS/SL 7.0 patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $? diff --git a/scripts/specialize-patch b/scripts/specialize-patch index ede8b0a19..dd0c842f2 100755 --- a/scripts/specialize-patch +++ b/scripts/specialize-patch @@ -251,7 +251,7 @@ function evaluate(stmnt, pattern, arg, op, result) { sub(pattern, op[1] == 0 ? op[2] : op[1], stmnt) } - pattern="\\((-*[0-9]+)\\)" + pattern="\\([[:blank:]]*(-*[0-9]+)[[:blank:]]*\\)" while (match(stmnt, pattern, op) != 0) { sub(pattern, op[1], stmnt) @@ -545,11 +545,17 @@ BEGIN { reset_hunk_state_variables() match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$", h) } - else if (delete_next_blank_line && match($0, "^+$")) + else if (delete_next_blank_line && $0 == "+") { discard = 1 delete_next_blank_line = 0 } + else if (lines >= 2 && !match(line[lines-2], ":$") && + line[lines-1] == "+\x9return;" && $0 == "+}") + { + line[lines-1] = $0 + lines_less_added++ + } else { delete_next_blank_line = 0 diff --git a/scst/kernel/in-tree/Kconfig.drivers.Linux-3.17.patch b/scst/kernel/in-tree/Kconfig.drivers.Linux-3.17.patch new file mode 100644 index 000000000..0d5a19f0f --- /dev/null +++ b/scst/kernel/in-tree/Kconfig.drivers.Linux-3.17.patch @@ -0,0 +1,13 @@ +diff --git a/drivers/Kconfig b/drivers/Kconfig +index aa43b91..c96860e 100644 +--- a/drivers/Kconfig ++++ b/drivers/Kconfig +@@ -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.dev_handlers-3.17 b/scst/kernel/in-tree/Makefile.dev_handlers-3.17 new file mode 100644 index 000000000..f933b36f7 --- /dev/null +++ b/scst/kernel/in-tree/Makefile.dev_handlers-3.17 @@ -0,0 +1,14 @@ +ccflags-y += -Wno-unused-parameter + +obj-m := scst_cdrom.o scst_changer.o scst_disk.o scst_modisk.o scst_tape.o \ + scst_vdisk.o scst_raid.o scst_processor.o scst_user.o + +obj-$(CONFIG_SCST_DISK) += scst_disk.o +obj-$(CONFIG_SCST_TAPE) += scst_tape.o +obj-$(CONFIG_SCST_CDROM) += scst_cdrom.o +obj-$(CONFIG_SCST_MODISK) += scst_modisk.o +obj-$(CONFIG_SCST_CHANGER) += scst_changer.o +obj-$(CONFIG_SCST_RAID) += scst_raid.o +obj-$(CONFIG_SCST_PROCESSOR) += scst_processor.o +obj-$(CONFIG_SCST_VDISK) += scst_vdisk.o +obj-$(CONFIG_SCST_USER) += scst_user.o diff --git a/scst/kernel/in-tree/Makefile.drivers.Linux-3.17.patch b/scst/kernel/in-tree/Makefile.drivers.Linux-3.17.patch new file mode 100644 index 000000000..f7213ed4c --- /dev/null +++ b/scst/kernel/in-tree/Makefile.drivers.Linux-3.17.patch @@ -0,0 +1,12 @@ +diff --git a/drivers/Makefile b/drivers/Makefile +index ab93de8..45077ec 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -128,6 +128,7 @@ obj-$(CONFIG_SSB) += ssb/ + obj-$(CONFIG_BCMA) += bcma/ + obj-$(CONFIG_VHOST_RING) += vhost/ + obj-$(CONFIG_VLYNQ) += vlynq/ ++obj-$(CONFIG_SCST) += scst/ + obj-$(CONFIG_STAGING) += staging/ + obj-y += platform/ + #common clk code diff --git a/scst/kernel/in-tree/Makefile.scst-3.17 b/scst/kernel/in-tree/Makefile.scst-3.17 new file mode 100644 index 000000000..53af5f388 --- /dev/null +++ b/scst/kernel/in-tree/Makefile.scst-3.17 @@ -0,0 +1,13 @@ +ccflags-y += -Wno-unused-parameter + +scst-y += scst_main.o +scst-y += scst_pres.o +scst-y += scst_targ.o +scst-y += scst_lib.o +scst-y += scst_sysfs.o +scst-y += scst_mem.o +scst-y += scst_tg.o +scst-y += scst_debug.o + +obj-$(CONFIG_SCST) += scst.o dev_handlers/ fcst/ iscsi-scst/ qla2xxx-target/ \ + srpt/ scst_local/ diff --git a/scst/kernel/scst_exec_req_fifo-3.17.patch b/scst/kernel/scst_exec_req_fifo-3.17.patch new file mode 100644 index 000000000..46215abb0 --- /dev/null +++ b/scst/kernel/scst_exec_req_fifo-3.17.patch @@ -0,0 +1,524 @@ +=== modified file 'block/blk-map.c' +--- old/block/blk-map.c 2014-11-21 03:17:49 +0000 ++++ new/block/blk-map.c 2014-11-21 03:43:00 +0000 +@@ -5,6 +5,8 @@ + #include + #include + #include ++#include ++#include + #include /* for struct sg_iovec */ + + #include "blk.h" +@@ -273,6 +275,333 @@ int blk_rq_unmap_user(struct bio *bio) + } + EXPORT_SYMBOL(blk_rq_unmap_user); + ++struct blk_kern_sg_work { ++ atomic_t bios_inflight; ++ struct sg_table sg_table; ++ struct scatterlist *src_sgl; ++}; ++ ++static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw) ++{ ++ struct sg_table *sgt = &bw->sg_table; ++ struct scatterlist *sg; ++ int i; ++ ++ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) { ++ struct page *pg = sg_page(sg); ++ if (pg == NULL) ++ break; ++ __free_page(pg); ++ } ++ ++ sg_free_table(sgt); ++ kfree(bw); ++ return; ++} ++ ++static void blk_bio_map_kern_endio(struct bio *bio, int err) ++{ ++ struct blk_kern_sg_work *bw = bio->bi_private; ++ ++ if (bw != NULL) { ++ /* Decrement the bios in processing and, if zero, free */ ++ BUG_ON(atomic_read(&bw->bios_inflight) <= 0); ++ if (atomic_dec_and_test(&bw->bios_inflight)) { ++ if ((bio_data_dir(bio) == READ) && (err == 0)) { ++ unsigned long flags; ++ ++ local_irq_save(flags); /* to protect KMs */ ++ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0); ++ local_irq_restore(flags); ++ } ++ blk_free_kern_sg_work(bw); ++ } ++ } ++ ++ bio_put(bio); ++ return; ++} ++ ++static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl, ++ int nents, struct blk_kern_sg_work **pbw, ++ gfp_t gfp, gfp_t page_gfp) ++{ ++ int res = 0, i; ++ struct scatterlist *sg; ++ struct scatterlist *new_sgl; ++ int new_sgl_nents; ++ size_t len = 0, to_copy; ++ struct blk_kern_sg_work *bw; ++ ++ bw = kzalloc(sizeof(*bw), gfp); ++ if (bw == NULL) ++ goto out; ++ ++ bw->src_sgl = sgl; ++ ++ for_each_sg(sgl, sg, nents, i) ++ len += sg->length; ++ to_copy = len; ++ ++ new_sgl_nents = PFN_UP(len); ++ ++ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp); ++ if (res != 0) ++ goto err_free; ++ ++ new_sgl = bw->sg_table.sgl; ++ ++ for_each_sg(new_sgl, sg, new_sgl_nents, i) { ++ struct page *pg; ++ ++ pg = alloc_page(page_gfp); ++ if (pg == NULL) ++ goto err_free; ++ ++ sg_assign_page(sg, pg); ++ sg->length = min_t(size_t, PAGE_SIZE, len); ++ ++ len -= PAGE_SIZE; ++ } ++ ++ if (rq_data_dir(rq) == WRITE) { ++ /* ++ * We need to limit amount of copied data to to_copy, because ++ * sgl might have the last element in sgl not marked as last in ++ * SG chaining. ++ */ ++ sg_copy(new_sgl, sgl, 0, to_copy); ++ } ++ ++ *pbw = bw; ++ /* ++ * REQ_COPY_USER name is misleading. It should be something like ++ * REQ_HAS_TAIL_SPACE_FOR_PADDING. ++ */ ++ rq->cmd_flags |= REQ_COPY_USER; ++ ++out: ++ return res; ++ ++err_free: ++ blk_free_kern_sg_work(bw); ++ res = -ENOMEM; ++ goto out; ++} ++ ++static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl, ++ int nents, struct blk_kern_sg_work *bw, gfp_t gfp) ++{ ++ int res; ++ struct request_queue *q = rq->q; ++ int rw = rq_data_dir(rq); ++ int max_nr_vecs, i; ++ size_t tot_len; ++ bool need_new_bio; ++ struct scatterlist *sg, *prev_sg = NULL; ++ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL; ++ int bios; ++ ++ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) { ++ WARN_ON(1); ++ res = -EINVAL; ++ goto out; ++ } ++ ++ /* ++ * Let's keep each bio allocation inside a single page to decrease ++ * probability of failure. ++ */ ++ max_nr_vecs = min_t(size_t, ++ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)), ++ BIO_MAX_PAGES); ++ ++ need_new_bio = true; ++ tot_len = 0; ++ bios = 0; ++ for_each_sg(sgl, sg, nents, i) { ++ struct page *page = sg_page(sg); ++ void *page_addr = page_address(page); ++ size_t len = sg->length, l; ++ size_t offset = sg->offset; ++ ++ tot_len += len; ++ prev_sg = sg; ++ ++ /* ++ * Each segment must be aligned on DMA boundary and ++ * not on stack. The last one may have unaligned ++ * length as long as the total length is aligned to ++ * DMA padding alignment. ++ */ ++ if (i == nents - 1) ++ l = 0; ++ else ++ l = len; ++ if (((sg->offset | l) & queue_dma_alignment(q)) || ++ (page_addr && object_is_on_stack(page_addr + sg->offset))) { ++ res = -EINVAL; ++ goto out_free_bios; ++ } ++ ++ while (len > 0) { ++ size_t bytes; ++ int rc; ++ ++ if (need_new_bio) { ++ bio = bio_kmalloc(gfp, max_nr_vecs); ++ if (bio == NULL) { ++ res = -ENOMEM; ++ goto out_free_bios; ++ } ++ ++ if (rw == WRITE) ++ bio->bi_rw |= REQ_WRITE; ++ ++ bios++; ++ bio->bi_private = bw; ++ bio->bi_end_io = blk_bio_map_kern_endio; ++ ++ if (hbio == NULL) ++ hbio = tbio = bio; ++ else ++ tbio = tbio->bi_next = bio; ++ } ++ ++ bytes = min_t(size_t, len, PAGE_SIZE - offset); ++ ++ rc = bio_add_pc_page(q, bio, page, bytes, offset); ++ if (rc < bytes) { ++ if (unlikely(need_new_bio || (rc < 0))) { ++ if (rc < 0) ++ res = rc; ++ else ++ res = -EIO; ++ goto out_free_bios; ++ } else { ++ need_new_bio = true; ++ len -= rc; ++ offset += rc; ++ continue; ++ } ++ } ++ ++ need_new_bio = false; ++ offset = 0; ++ len -= bytes; ++ page = nth_page(page, 1); ++ } ++ } ++ ++ if (hbio == NULL) { ++ res = -EINVAL; ++ goto out_free_bios; ++ } ++ ++ /* Total length must be aligned on DMA padding alignment */ ++ if ((tot_len & q->dma_pad_mask) && ++ !(rq->cmd_flags & REQ_COPY_USER)) { ++ res = -EINVAL; ++ goto out_free_bios; ++ } ++ ++ if (bw != NULL) ++ atomic_set(&bw->bios_inflight, bios); ++ ++ while (hbio != NULL) { ++ bio = hbio; ++ hbio = hbio->bi_next; ++ bio->bi_next = NULL; ++ ++ blk_queue_bounce(q, &bio); ++ ++ res = blk_rq_append_bio(q, rq, bio); ++ if (unlikely(res != 0)) { ++ bio->bi_next = hbio; ++ hbio = bio; ++ /* We can have one or more bios bounced */ ++ goto out_unmap_bios; ++ } ++ } ++ ++ res = 0; ++out: ++ return res; ++ ++out_unmap_bios: ++ blk_rq_unmap_kern_sg(rq, res); ++ ++out_free_bios: ++ while (hbio != NULL) { ++ bio = hbio; ++ hbio = hbio->bi_next; ++ bio_put(bio); ++ } ++ goto out; ++} ++ ++/** ++ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC ++ * @rq: request to fill ++ * @sgl: area to map ++ * @nents: number of elements in @sgl ++ * @gfp: memory allocation flags ++ * ++ * Description: ++ * Data will be mapped directly if possible. Otherwise a bounce ++ * buffer will be used. ++ */ ++int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl, ++ int nents, gfp_t gfp) ++{ ++ int res; ++ ++ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp); ++ if (unlikely(res != 0)) { ++ struct blk_kern_sg_work *bw = NULL; ++ ++ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw, ++ gfp, rq->q->bounce_gfp | gfp); ++ if (unlikely(res != 0)) ++ goto out; ++ ++ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl, ++ bw->sg_table.nents, bw, gfp); ++ if (res != 0) { ++ blk_free_kern_sg_work(bw); ++ goto out; ++ } ++ } ++ ++out: ++ return res; ++} ++EXPORT_SYMBOL(blk_rq_map_kern_sg); ++ ++/** ++ * blk_rq_unmap_kern_sg - unmap a request with kernel sg ++ * @rq: request to unmap ++ * @err: non-zero error code ++ * ++ * Description: ++ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called ++ * only in case of an error! ++ */ ++void blk_rq_unmap_kern_sg(struct request *rq, int err) ++{ ++ struct bio *bio = rq->bio; ++ ++ while (bio) { ++ struct bio *b = bio; ++ bio = bio->bi_next; ++ b->bi_end_io(b, err); ++ } ++ rq->bio = NULL; ++ ++ return; ++} ++EXPORT_SYMBOL(blk_rq_unmap_kern_sg); ++ + /** + * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage + * @q: request queue where request should be inserted + +=== modified file 'include/linux/blkdev.h' +--- old/include/linux/blkdev.h 2014-11-21 03:17:49 +0000 ++++ new/include/linux/blkdev.h 2014-11-21 03:43:00 +0000 +@@ -737,6 +737,8 @@ extern unsigned long blk_max_low_pfn, bl + #define BLK_DEFAULT_SG_TIMEOUT (60 * HZ) + #define BLK_MIN_SG_TIMEOUT (7 * HZ) + ++#define SCSI_EXEC_REQ_FIFO_DEFINED ++ + #ifdef CONFIG_BOUNCE + extern int init_emergency_isa_pool(void); + extern void blk_queue_bounce(struct request_queue *q, struct bio **bio); +@@ -858,6 +860,9 @@ extern int blk_rq_map_kern(struct reques + extern int blk_rq_map_user_iov(struct request_queue *, struct request *, + struct rq_map_data *, const struct sg_iovec *, + int, unsigned int, gfp_t); ++extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl, ++ int nents, gfp_t gfp); ++extern void blk_rq_unmap_kern_sg(struct request *rq, int err); + extern int blk_execute_rq(struct request_queue *, struct gendisk *, + struct request *, int); + extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, + +=== modified file 'include/linux/scatterlist.h' +--- old/include/linux/scatterlist.h 2014-11-21 03:17:49 +0000 ++++ new/include/linux/scatterlist.h 2014-11-21 03:43:00 +0000 +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + struct sg_table { + struct scatterlist *sgl; /* the list */ +@@ -249,6 +250,9 @@ size_t sg_pcopy_from_buffer(struct scatt + size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, + void *buf, size_t buflen, off_t skip); + ++int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg, ++ int nents_to_copy, size_t copy_len); ++ + /* + * Maximum number of entries that will be allocated in one piece, if + * a list larger than this is required then chaining will be utilized. + +=== modified file 'lib/scatterlist.c' +--- old/lib/scatterlist.c 2014-11-21 03:17:49 +0000 ++++ new/lib/scatterlist.c 2014-11-21 03:43:00 +0000 +@@ -727,3 +727,127 @@ size_t sg_pcopy_to_buffer(struct scatter + return sg_copy_buffer(sgl, nents, buf, buflen, skip, true); + } + EXPORT_SYMBOL(sg_pcopy_to_buffer); ++ ++ ++/* ++ * Can switch to the next dst_sg element, so, to copy to strictly only ++ * one dst_sg element, it must be either last in the chain, or ++ * copy_len == dst_sg->length. ++ */ ++static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len, ++ size_t *pdst_offs, struct scatterlist *src_sg, ++ size_t copy_len) ++{ ++ int res = 0; ++ struct scatterlist *dst_sg; ++ size_t src_len, dst_len, src_offs, dst_offs; ++ struct page *src_page, *dst_page; ++ ++ dst_sg = *pdst_sg; ++ dst_len = *pdst_len; ++ dst_offs = *pdst_offs; ++ dst_page = sg_page(dst_sg); ++ ++ src_page = sg_page(src_sg); ++ src_len = src_sg->length; ++ src_offs = src_sg->offset; ++ ++ do { ++ void *saddr, *daddr; ++ size_t n; ++ ++ saddr = kmap_atomic(src_page + (src_offs >> PAGE_SHIFT)) + ++ (src_offs & ~PAGE_MASK); ++ daddr = kmap_atomic(dst_page + (dst_offs >> PAGE_SHIFT)) + ++ (dst_offs & ~PAGE_MASK); ++ ++ if (((src_offs & ~PAGE_MASK) == 0) && ++ ((dst_offs & ~PAGE_MASK) == 0) && ++ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) && ++ (copy_len >= PAGE_SIZE)) { ++ copy_page(daddr, saddr); ++ n = PAGE_SIZE; ++ } else { ++ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK), ++ PAGE_SIZE - (src_offs & ~PAGE_MASK)); ++ n = min(n, src_len); ++ n = min(n, dst_len); ++ n = min_t(size_t, n, copy_len); ++ memcpy(daddr, saddr, n); ++ } ++ dst_offs += n; ++ src_offs += n; ++ ++ kunmap_atomic(saddr); ++ kunmap_atomic(daddr); ++ ++ res += n; ++ copy_len -= n; ++ if (copy_len == 0) ++ goto out; ++ ++ src_len -= n; ++ dst_len -= n; ++ if (dst_len == 0) { ++ dst_sg = sg_next(dst_sg); ++ if (dst_sg == NULL) ++ goto out; ++ dst_page = sg_page(dst_sg); ++ dst_len = dst_sg->length; ++ dst_offs = dst_sg->offset; ++ } ++ } while (src_len > 0); ++ ++out: ++ *pdst_sg = dst_sg; ++ *pdst_len = dst_len; ++ *pdst_offs = dst_offs; ++ return res; ++} ++ ++/** ++ * sg_copy - copy one SG vector to another ++ * @dst_sg: destination SG ++ * @src_sg: source SG ++ * @nents_to_copy: maximum number of entries to copy ++ * @copy_len: maximum amount of data to copy. If 0, then copy all. ++ * ++ * Description: ++ * Data from the source SG vector will be copied to the destination SG ++ * vector. End of the vectors will be determined by sg_next() returning ++ * NULL. Returns number of bytes copied. ++ */ ++int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg, ++ int nents_to_copy, size_t copy_len) ++{ ++ int res = 0; ++ size_t dst_len, dst_offs; ++ ++ if (copy_len == 0) ++ copy_len = 0x7FFFFFFF; /* copy all */ ++ ++ if (nents_to_copy == 0) ++ nents_to_copy = 0x7FFFFFFF; /* copy all */ ++ ++ dst_len = dst_sg->length; ++ dst_offs = dst_sg->offset; ++ ++ do { ++ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs, ++ src_sg, copy_len); ++ copy_len -= copied; ++ res += copied; ++ if ((copy_len == 0) || (dst_sg == NULL)) ++ goto out; ++ ++ nents_to_copy--; ++ if (nents_to_copy == 0) ++ goto out; ++ ++ src_sg = sg_next(src_sg); ++ } while (src_sg != NULL); ++ ++out: ++ return res; ++} ++EXPORT_SYMBOL(sg_copy); + diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index 1d4b34faf..ec4e85bc8 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -214,9 +214,9 @@ static int tape_attach(struct scst_device *dev) mode = (buffer[2] & 0x70) >> 4; speed = buffer[2] & 0x0f; density = buffer[4]; - TRACE_DBG("Tape: lun %d. bs %d. type 0x%02x mode 0x%02x " - "speed 0x%02x dens 0x%02x", dev->scsi_dev->lun, - dev->block_size, medium_type, mode, speed, density); + TRACE_DBG("Tape: lun %lld. bs %d. type 0x%02x mode 0x%02x " + "speed 0x%02x dens 0x%02x", (u64)dev->scsi_dev->lun, + dev->block_size, medium_type, mode, speed, density); } else { PRINT_ERROR("MODE_SENSE failed: %x", rc); res = -ENODEV; diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index a5d7726c5..8aa6576dc 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -4887,7 +4887,7 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) loff_t loff = p->loff; mm_segment_t old_fs; loff_t err = 0; - ssize_t length, full_len, saved_full_len; + ssize_t length, full_len; uint8_t __user *address; struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv; struct file *fd = virt_dev->fd; @@ -4943,7 +4943,6 @@ static enum compl_status_e fileio_exec_write(struct vdisk_cmd_params *p) goto out_set_fs; } - saved_full_len = full_len; eiv = iv; eiv_count = iv_count; restart: diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 1b5552bc4..44132e9e8 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -6666,7 +6666,7 @@ static int get_cdb_info_read_pos(struct scst_cmd *cmd, cmd->bufflen = 32; break; case 8: - cmd->bufflen = max(28, cmd->bufflen); + cmd->bufflen = max(32, cmd->bufflen); break; default: PRINT_ERROR("READ POSITION: Invalid service action %x", @@ -9042,16 +9042,11 @@ static void scst_process_qerr(struct scst_cmd *cmd) int scst_process_check_condition(struct scst_cmd *cmd) { int res; - struct scst_order_data *order_data; - struct scst_device *dev; TRACE_ENTRY(); EXTRACHECKS_BUG_ON(test_bit(SCST_CMD_NO_RESP, &cmd->cmd_flags)); - order_data = cmd->cur_order_data; - dev = cmd->dev; - TRACE_DBG("CHECK CONDITION for cmd %p (tgt_dev %p)", cmd, cmd->tgt_dev); scst_process_qerr(cmd); diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 3baead81b..e89642510 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -1051,6 +1051,7 @@ EXPORT_SYMBOL_GPL(scst_suspend_activity); static void __scst_resume_activity(void) { struct scst_cmd_threads *l; + struct scst_mgmt_cmd *m; TRACE_ENTRY(); @@ -1077,15 +1078,14 @@ static void __scst_resume_activity(void) wake_up_all(&scst_init_cmd_list_waitQ); spin_lock_irq(&scst_mcmd_lock); - if (!list_empty(&scst_delayed_mgmt_cmd_list)) { - struct scst_mgmt_cmd *m; - m = list_first_entry(&scst_delayed_mgmt_cmd_list, typeof(*m), - mgmt_cmd_list_entry); + list_for_each_entry(m, &scst_delayed_mgmt_cmd_list, + mgmt_cmd_list_entry) { TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active " "mgmt cmd list", m); - list_move(&m->mgmt_cmd_list_entry, &scst_active_mgmt_cmd_list); } + list_splice(&scst_delayed_mgmt_cmd_list, &scst_active_mgmt_cmd_list); spin_unlock_irq(&scst_mcmd_lock); + wake_up_all(&scst_mgmt_cmd_list_waitQ); out: @@ -1145,9 +1145,9 @@ static int scst_register_device(struct scsi_device *scsidp) dev->type = scsidp->type; - dev->virt_name = kasprintf(GFP_KERNEL, "%d:%d:%d:%d", - scsidp->host->host_no, - scsidp->channel, scsidp->id, scsidp->lun); + dev->virt_name = kasprintf(GFP_KERNEL, "%d:%d:%d:%lld", + scsidp->host->host_no, scsidp->channel, + scsidp->id, (u64)scsidp->lun); if (dev->virt_name == NULL) { PRINT_ERROR("%s", "Unable to alloc device name"); res = -ENOMEM; @@ -1190,9 +1190,9 @@ static int scst_register_device(struct scsi_device *scsidp) goto out_del_unlocked; #endif - PRINT_INFO("Attached to scsi%d, channel %d, id %d, lun %d, " - "type %d", scsidp->host->host_no, scsidp->channel, - scsidp->id, scsidp->lun, scsidp->type); + PRINT_INFO("Attached to scsi%d, channel %d, id %d, lun %lld, type %d", + scsidp->host->host_no, scsidp->channel, scsidp->id, + (u64)scsidp->lun, scsidp->type); out: TRACE_EXIT_RES(res); @@ -1259,9 +1259,9 @@ static void scst_unregister_device(struct scsi_device *scsidp) } if (dev == NULL) { - PRINT_ERROR("SCST device for SCSI device %d:%d:%d:%d not found", - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun); + PRINT_ERROR("SCST device for SCSI device %d:%d:%d:%lld not found", + scsidp->host->host_no, scsidp->channel, scsidp->id, + (u64)scsidp->lun); goto out_unlock; } @@ -1285,9 +1285,9 @@ static void scst_unregister_device(struct scsi_device *scsidp) scst_dev_sysfs_del(dev); - PRINT_INFO("Detached from scsi%d, channel %d, id %d, lun %d, type %d", - scsidp->host->host_no, scsidp->channel, scsidp->id, - scsidp->lun, scsidp->type); + PRINT_INFO("Detached from scsi%d, channel %d, id %d, lun %lld, type %d", + scsidp->host->host_no, scsidp->channel, scsidp->id, + (u64)scsidp->lun, scsidp->type); scst_free_device(dev); diff --git a/scst/src/scst_pres.c b/scst/src/scst_pres.c index f5995e210..cc06ac361 100644 --- a/scst/src/scst_pres.c +++ b/scst/src/scst_pres.c @@ -858,15 +858,16 @@ out: static void scst_pr_remove_device_files(struct scst_tgt_dev *tgt_dev) { - int res = 0; struct scst_device *dev = tgt_dev->dev; TRACE_ENTRY(); scst_assert_pr_mutex_held(dev); - res = dev->pr_file_name ? scst_remove_file(dev->pr_file_name) : -ENOENT; - res = dev->pr_file_name1 ? scst_remove_file(dev->pr_file_name1) : -ENOENT; + if (dev->pr_file_name) + scst_remove_file(dev->pr_file_name); + if (dev->pr_file_name1) + scst_remove_file(dev->pr_file_name1); TRACE_EXIT(); return; diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 6ee2b2ef1..16072fc86 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -313,7 +313,9 @@ out: #endif /* defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) && \ + (!defined(RHEL_MAJOR) || RHEL_MAJOR -0 < 6 || \ + (RHEL_MAJOR -0 == 6 && RHEL_MINOR -0 < 6)) /** ** Backported sysfs functions. **/ @@ -5081,7 +5083,8 @@ static int scst_process_devt_pass_through_mgmt_store(char *buffer, { int res = 0; char *pp, *action, *devstr; - unsigned int host, channel, id, lun; + unsigned int host, channel, id; + u64 lun; struct scst_device *d, *dev = NULL; TRACE_ENTRY(); @@ -5103,10 +5106,10 @@ static int scst_process_devt_pass_through_mgmt_store(char *buffer, goto out_syntax_err; } - if (sscanf(devstr, "%u:%u:%u:%u", &host, &channel, &id, &lun) != 4) + if (sscanf(devstr, "%u:%u:%u:%llu", &host, &channel, &id, &lun) != 4) goto out_syntax_err; - TRACE_DBG("Dev %d:%d:%d:%d", host, channel, id, lun); + TRACE_DBG("Dev %d:%d:%d:%lld", host, channel, id, lun); res = mutex_lock_interruptible(&scst_mutex); if (res != 0) @@ -5123,13 +5126,13 @@ static int scst_process_devt_pass_through_mgmt_store(char *buffer, d->scsi_dev->id == id && d->scsi_dev->lun == lun) { dev = d; - TRACE_DBG("Dev %p (%d:%d:%d:%d) found", + TRACE_DBG("Dev %p (%d:%d:%d:%lld) found", dev, host, channel, id, lun); break; } } if (dev == NULL) { - PRINT_ERROR("Device %d:%d:%d:%d not found", + PRINT_ERROR("Device %d:%d:%d:%lld not found", host, channel, id, lun); res = -EINVAL; goto out_unlock; diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 036a1d753..175af61bf 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -6021,6 +6021,8 @@ static int scst_lun_reset(struct scst_mgmt_cmd *mcmd) TRACE(TRACE_MGMT, "Resetting host %d bus ", dev->scsi_dev->host->host_no); rc = scsi_reset_provider(dev->scsi_dev, SCSI_TRY_RESET_DEVICE); + TRACE(TRACE_MGMT, "scsi_reset_provider(%s) returned %d", + dev->virt_name, rc); #if 0 if (rc != SUCCESS && mcmd->status == SCST_MGMT_STATUS_SUCCESS) scst_mgmt_cmd_set_status(mcmd, SCST_MGMT_STATUS_FAILED); diff --git a/scst_local/in-tree/Makefile-3.17 b/scst_local/in-tree/Makefile-3.17 new file mode 100644 index 000000000..8cbbbff63 --- /dev/null +++ b/scst_local/in-tree/Makefile-3.17 @@ -0,0 +1,2 @@ +obj-$(CONFIG_SCST_LOCAL) += scst_local.o + diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index e872bdeaa..88c684075 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -142,6 +142,8 @@ struct scst_local_sess { spinlock_t aen_lock; struct list_head aen_work_list; /* protected by aen_lock */ + struct work_struct remove_work; + struct list_head sessions_list_entry; }; @@ -152,6 +154,8 @@ static int __scst_local_add_adapter(struct scst_local_tgt *tgt, const char *initiator_name, bool locked); static int scst_local_add_adapter(struct scst_local_tgt *tgt, const char *initiator_name); +static void scst_local_close_session_impl(struct scst_local_sess *sess, + bool async); static void scst_local_remove_adapter(struct scst_local_sess *sess); static int scst_local_add_target(const char *target_name, struct scst_local_tgt **out_tgt); @@ -786,7 +790,7 @@ static ssize_t scst_local_sysfs_mgmt_cmd(char *buf) res = -EINVAL; goto out_unlock; } - scst_local_remove_adapter(sess); + scst_local_close_session_impl(sess, false); } res = 0; @@ -831,7 +835,7 @@ static int scst_local_abort(struct scsi_cmnd *SCpnt) static int scst_local_device_reset(struct scsi_cmnd *SCpnt) { struct scst_local_sess *sess; - __be16 lun; + struct scsi_lun lun; int ret; DECLARE_COMPLETION_ONSTACK(dev_reset_completion); @@ -839,10 +843,11 @@ static int scst_local_device_reset(struct scsi_cmnd *SCpnt) sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host)); - lun = cpu_to_be16(SCpnt->device->lun); + int_to_scsilun(SCpnt->device->lun, &lun); ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET, - &lun, sizeof(lun), false, &dev_reset_completion); + lun.scsi_lun, sizeof(lun), false, + &dev_reset_completion); /* Now wait for the completion ... */ wait_for_completion_interruptible(&dev_reset_completion); @@ -860,7 +865,7 @@ static int scst_local_device_reset(struct scsi_cmnd *SCpnt) static int scst_local_target_reset(struct scsi_cmnd *SCpnt) { struct scst_local_sess *sess; - __be16 lun; + struct scsi_lun lun; int ret; DECLARE_COMPLETION_ONSTACK(dev_reset_completion); @@ -868,10 +873,11 @@ static int scst_local_target_reset(struct scsi_cmnd *SCpnt) sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host)); - lun = cpu_to_be16(SCpnt->device->lun); + int_to_scsilun(SCpnt->device->lun, &lun); ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET, - &lun, sizeof(lun), false, &dev_reset_completion); + lun.scsi_lun, sizeof(lun), false, + &dev_reset_completion); /* Now wait for the completion ... */ wait_for_completion_interruptible(&dev_reset_completion); @@ -953,13 +959,14 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, struct scst_local_sess *sess; struct scatterlist *sgl = NULL; int sgl_count = 0; - __be16 lun; + struct scsi_lun lun; struct scst_cmd *scst_cmd = NULL; scst_data_direction dir; TRACE_ENTRY(); - TRACE_DBG("lun %d, cmd: 0x%02X", SCpnt->device->lun, SCpnt->cmnd[0]); + TRACE_DBG("lun %lld, cmd: 0x%02X", (u64)SCpnt->device->lun, + SCpnt->cmnd[0]); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) /* @@ -1002,9 +1009,9 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, * get into mem alloc deadlock when mounting file systems over * our devices. */ - lun = cpu_to_be16(SCpnt->device->lun); - scst_cmd = scst_rx_cmd(sess->scst_sess, (const uint8_t *)&lun, - sizeof(lun), SCpnt->cmnd, SCpnt->cmd_len, true); + int_to_scsilun(SCpnt->device->lun, &lun); + scst_cmd = scst_rx_cmd(sess->scst_sess, lun.scsi_lun, sizeof(lun), + SCpnt->cmnd, SCpnt->cmd_len, true); if (!scst_cmd) { PRINT_ERROR("%s", "scst_rx_cmd() failed"); return SCSI_MLQUEUE_HOST_BUSY; @@ -1148,14 +1155,15 @@ static int scst_local_get_max_queue_depth(struct scsi_device *sdev) { int res; struct scst_local_sess *sess; - __be16 lun; + struct scsi_lun lun; TRACE_ENTRY(); sess = to_scst_lcl_sess(scsi_get_device(sdev->host)); - lun = cpu_to_be16(sdev->lun); + int_to_scsilun(sdev->lun, &lun); res = scst_get_max_lun_commands(sess->scst_sess, - scst_unpack_lun((const uint8_t *)&lun, sizeof(lun))); + scst_unpack_lun(lun.scsi_lun, + sizeof(lun))); TRACE_EXIT_RES(res); return res; @@ -1385,6 +1393,56 @@ static int scst_local_targ_release(struct scst_tgt *tgt) return 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void scst_remove_work_fn(void *ctx) +#else +static void scst_remove_work_fn(struct work_struct *work) +#endif +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + struct scst_local_sess *sess = ctx; +#else + struct scst_local_sess *sess = + container_of(work, struct scst_local_sess, remove_work); +#endif + + scst_local_remove_adapter(sess); +} + +static void scst_local_close_session_impl(struct scst_local_sess *sess, + bool async) +{ + bool unregistering; + + spin_lock(&sess->aen_lock); + unregistering = sess->unregistering; + sess->unregistering = 1; + spin_unlock(&sess->aen_lock); + + if (!unregistering) { + if (async) + schedule_work(&sess->remove_work); + else + scst_local_remove_adapter(sess); + } +} + +/* + * Perform removal from the context of another thread since the caller may + * already hold an SCST mutex, since scst_local_remove_adapter() triggers a + * call of device_unregister(), since device_unregister() invokes + * device_del(), since device_del() locks the same mutex that is held while + * invoking scst_add() from class_interface_register() and since scst_add() + * also may lock an SCST mutex. + */ +static int scst_local_close_session(struct scst_session *scst_sess) +{ + struct scst_local_sess *sess = scst_sess_get_tgt_priv(scst_sess); + + scst_local_close_session_impl(sess, true); + return 0; +} + static int scst_local_targ_xmit_response(struct scst_cmd *scst_cmd) { #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) @@ -1525,6 +1583,7 @@ static struct scst_tgt_template scst_local_targ_tmpl = { #endif .detect = scst_local_targ_detect, .release = scst_local_targ_release, + .close_session = scst_local_close_session, .pre_exec = scst_local_targ_pre_exec, .xmit_response = scst_local_targ_xmit_response, #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) @@ -1618,8 +1677,8 @@ static int scst_local_driver_probe(struct device *dev) sess->shost = hpnt; - hpnt->max_id = 0; /* Don't want more than one id */ - hpnt->max_lun = 0xFFFF; + hpnt->max_id = 1; /* Don't want more than one id */ + hpnt->max_lun = -1ll; /* * Because of a change in the size of this field at 2.6.26 @@ -1783,8 +1842,10 @@ static int __scst_local_add_adapter(struct scst_local_tgt *tgt, */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)) INIT_WORK(&sess->aen_work, scst_aen_work_fn, sess); + INIT_WORK(&sess->remove_work, scst_remove_work_fn, sess); #else INIT_WORK(&sess->aen_work, scst_aen_work_fn); + INIT_WORK(&sess->remove_work, scst_remove_work_fn); #endif spin_lock_init(&sess->aen_lock); INIT_LIST_HEAD(&sess->aen_work_list); @@ -1927,11 +1988,7 @@ static void __scst_local_remove_target(struct scst_local_tgt *tgt) list_for_each_entry_safe(sess, ts, &tgt->sessions_list, sessions_list_entry) { - spin_lock(&sess->aen_lock); - sess->unregistering = 1; - spin_unlock(&sess->aen_lock); - - scst_local_remove_adapter(sess); + scst_local_close_session_impl(sess, false); } list_del(&tgt->tgts_list_entry); diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t index 2aa100c6a..883f020f3 100644 --- a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/06-cont-on-err.t @@ -46,7 +46,7 @@ sub testRestoreConfig { system("$scstadmin -cont_on_err -no_lip -config $to_be_restored" . " >/dev/null"); system("$scstadmin -write_config $tmpfilename1 >/dev/null"); - system("awk 'BEGIN {t = 0 } /^TARGET_DRIVER.*{\$/ { if (\$0 != \"TARGET_DRIVER scst_local {\") t = 1 } /^}\$/ { if (t == 1) t = 2 } /^\$/ { if (t == 2) { t = 3 } } /^./ { if (t == 3) { t = 0 } } { if (t == 0) print }' <$tmpfilename1 >$tmpfilename2"); + system("awk 'BEGIN {t = 0 } /^# Automatically generated by SCST Configurator v/ { \$0 = \"# Automatically generated by SCST Configurator v...\" } /^TARGET_DRIVER.*{\$/ { if (\$0 != \"TARGET_DRIVER scst_local {\") t = 1 } /^}\$/ { if (t == 1) t = 2 } /^\$/ { if (t == 2) { t = 3 } } /^./ { if (t == 3) { t = 0 } } { if (t == 0) print }' <$tmpfilename1 >$tmpfilename2"); my $compare_result = system("diff -u $tmpfilename2 $expected"); ok($compare_result, 0); if ($compare_result == 0) { diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf index a6ee39010..da8c75c37 100644 --- a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/after-restore.conf @@ -1,4 +1,4 @@ -# Automatically generated by SCST Configurator v3.0.0. +# Automatically generated by SCST Configurator v... HANDLER vdisk_fileio { diff --git a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf index 7d9229b6c..b4988b721 100644 --- a/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf +++ b/scstadmin/scstadmin.sysfs/scst-0.9.10/t/to-be-restored.conf @@ -1,4 +1,4 @@ -# Automatically generated by SCST Configurator v3.0.0. +# Automatically generated by SCST Configurator v3.0.0-pre2. HANDLER vdisk_fileio { diff --git a/scstadmin/scstadmin.sysfs/scstadmin b/scstadmin/scstadmin.sysfs/scstadmin index 14b2b849f..5e277259b 100755 --- a/scstadmin/scstadmin.sysfs/scstadmin +++ b/scstadmin/scstadmin.sysfs/scstadmin @@ -1751,6 +1751,8 @@ sub writeConfiguration { } } + $io->flush; + $io->sync; close $io; return 0; diff --git a/srpt/patches/kernel-3.17-pre-cflags.patch b/srpt/patches/kernel-3.17-pre-cflags.patch new file mode 100644 index 000000000..3964ee179 --- /dev/null +++ b/srpt/patches/kernel-3.17-pre-cflags.patch @@ -0,0 +1,12 @@ +diff --git a/Makefile b/Makefile +index 540f7b2..078307f 100644 +--- a/Makefile ++++ b/Makefile +@@ -361,6 +361,7 @@ USERINCLUDE := \ + # Use LINUXINCLUDE when you must reference the include/ directory. + # Needed to be compatible with the O= option + LINUXINCLUDE := \ ++ $(PRE_CFLAGS) \ + -I$(srctree)/arch/$(hdr-arch)/include \ + -Iarch/$(hdr-arch)/include/generated \ + $(if $(KBUILD_SRC), -I$(srctree)/include) \ diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index ce30c7bb2..d6505983c 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -2285,11 +2285,12 @@ static void __srpt_close_all_ch(struct srpt_tgt *srpt_tgt) list_for_each_entry(nexus, &srpt_tgt->nexus_list, entry) { list_for_each_entry(ch, &nexus->ch_list, list) { - if (srpt_disconnect_ch(ch) < 0) - continue; - PRINT_INFO("Closing channel %s because target %s has" - " been disabled", ch->sess_name, - srpt_tgt->scst_tgt->tgt_name); + if (srpt_disconnect_ch(ch) >= 0) + PRINT_INFO("Closing channel %s-%d because" + " target %s has been disabled", + ch->sess_name, ch->qp->qp_num, + srpt_tgt->scst_tgt->tgt_name); + srpt_close_ch(ch); } } }