From 73e27412fb9b5a7c1899c7da951e4bc703030aec Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 24 Jul 2008 09:22:55 +0000 Subject: [PATCH] - Update for 2.6.26 - Zero-copy feature, introduced by put_page_callback patch, made kernel compile time configurable via CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION option. If you upgrade from earlier versions, see the corresponding "[CAUTION]" e-mail in scst-devel mailing list about possible compatibility problems. - SRP target temporary removed from "all" and "install" the main Makefile targets, since it isn't compiled on 2.6.26 - Minor fixes and cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@475 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- Makefile | 4 +- iscsi-scst/ChangeLog | 13 + iscsi-scst/kernel/iscsi.c | 20 +- iscsi-scst/kernel/iscsi.h | 4 +- iscsi-scst/kernel/nthread.c | 12 +- .../patches/put_page_callback-2.6.16.29.patch | 2 +- .../patches/put_page_callback-2.6.18.1.patch | 2 +- .../patches/put_page_callback-2.6.21.1.patch | 2 +- .../patches/put_page_callback-2.6.22.patch | 2 +- .../patches/put_page_callback-2.6.23.patch | 2 +- .../patches/put_page_callback-2.6.24.patch | 2 +- .../patches/put_page_callback-2.6.25.patch | 2 +- .../patches/put_page_callback-2.6.26.patch | 297 ++++++++++++++++++ scst/ChangeLog | 3 + scst/kernel/scst_exec_req_fifo-2.6.26.patch | 109 +++++++ scst/src/dev_handlers/scst_user.c | 64 +++- scst/src/scst_main.c | 27 +- 17 files changed, 524 insertions(+), 43 deletions(-) create mode 100644 iscsi-scst/kernel/patches/put_page_callback-2.6.26.patch create mode 100644 scst/kernel/scst_exec_req_fifo-2.6.26.patch diff --git a/Makefile b/Makefile index 6576a9c7f..68de2f883 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,7 @@ all: @if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi # @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi # @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi - @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi +# @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi @if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi @if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi @@ -105,7 +105,7 @@ install: @if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi # @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi # @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi - @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi +# @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi @if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) DISTDIR=$(ISCSI_DISTDIR) $@; fi @if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi diff --git a/iscsi-scst/ChangeLog b/iscsi-scst/ChangeLog index e8abd0efe..837b521d5 100644 --- a/iscsi-scst/ChangeLog +++ b/iscsi-scst/ChangeLog @@ -1,3 +1,16 @@ +Summary of changes in iSCSI-SCST between versions 1.0.0 and 1.0.1 +----------------------------------------------------------------- + + - Update for 2.6.26 + + - Zero-copy feature, introduced by put_page_callback patch made + kernel compile time configurable via + CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION option. If you + upgrade from earlier versions, see the corresponding "[CAUTION]" + e-mail in scst-devel mailing list about possible compatibility + problems. + + Summary of changes in iSCSI-SCST since it was IET ------------------------------------------------- diff --git a/iscsi-scst/kernel/iscsi.c b/iscsi-scst/kernel/iscsi.c index a72f0b751..d0378bd5c 100644 --- a/iscsi-scst/kernel/iscsi.c +++ b/iscsi-scst/kernel/iscsi.c @@ -23,7 +23,7 @@ #include "iscsi.h" #include "digest.h" -#ifndef NET_PAGE_CALLBACKS_DEFINED +#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) #warning "Patch put_page_callback-.patch not applied on your \ kernel. ISCSI-SCST will run in the performance degraded mode. Refer \ README file for details." @@ -146,7 +146,7 @@ struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn, struct iscsi_cmnd *parent if (parent == NULL) { conn_get(conn); -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) atomic_set(&cmnd->net_ref_cnt, 0); #endif spin_lock_init(&cmnd->rsp_cmd_lock); @@ -1149,7 +1149,7 @@ static int iscsi_pre_exec(struct scst_cmd *scst_cmd) if (scst_cmd_get_data_direction(scst_cmd) == SCST_DATA_READ) { if (!(req->conn->ddigest_type & DIGEST_NONE)) scst_set_long_xmit(scst_cmd); -#ifndef NET_PAGE_CALLBACKS_DEFINED +#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) else if (cmnd_hdr(req)->data_length > 8*1024) scst_set_long_xmit(scst_cmd); #endif @@ -1315,7 +1315,7 @@ static int scsi_cmnd_start(struct iscsi_cmnd *req) req->scst_cmd = scst_cmd; scst_cmd_set_tag(scst_cmd, req_hdr->itt); scst_cmd_set_tgt_priv(scst_cmd, req); -#ifndef NET_PAGE_CALLBACKS_DEFINED +#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) scst_cmd_set_data_buf_tgt_alloc(scst_cmd); #endif @@ -1593,7 +1593,7 @@ static void __cmnd_abort(struct iscsi_cmnd *cmnd) cmnd->conn->session->exp_cmd_sn, cmnd->conn, cmnd->conn->rd_task); -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) TRACE_MGMT_DBG("net_ref_cnt %d", atomic_read(&cmnd->net_ref_cnt)); #endif @@ -2441,7 +2441,7 @@ out_rejected: goto out; } -#ifndef NET_PAGE_CALLBACKS_DEFINED +#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) static int iscsi_alloc_data_buf(struct scst_cmd *cmd) { if (scst_cmd_get_data_direction(cmd) == SCST_DATA_READ) { @@ -2846,7 +2846,7 @@ struct scst_tgt_template iscsi_template = { .detect = iscsi_target_detect, .release = iscsi_target_release, .xmit_response = iscsi_xmit_response, -#ifndef NET_PAGE_CALLBACKS_DEFINED +#if !defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) .alloc_data_buf = iscsi_alloc_data_buf, #endif .preprocessing_done = iscsi_preprocessing_done, @@ -2902,7 +2902,7 @@ static int __init iscsi_init(void) PRINT_INFO("iSCSI SCST Target - version %s", ISCSI_VERSION_STRING); -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) err = net_set_get_put_page_callbacks(iscsi_get_page_callback, iscsi_put_page_callback); if (err != 0) { @@ -2972,7 +2972,7 @@ out_reg: unregister_chrdev(ctr_major, ctr_name); out_callb: -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) net_set_get_put_page_callbacks(NULL, NULL); #endif goto out; @@ -2991,7 +2991,7 @@ static void __exit iscsi_exit(void) scst_unregister_target_template(&iscsi_template); -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) net_set_get_put_page_callbacks(NULL, NULL); #endif } diff --git a/iscsi-scst/kernel/iscsi.h b/iscsi-scst/kernel/iscsi.h index ba3b790df..e7afc2e62 100644 --- a/iscsi-scst/kernel/iscsi.h +++ b/iscsi-scst/kernel/iscsi.h @@ -300,7 +300,7 @@ struct iscsi_cmnd { int scst_state; struct scst_cmd *scst_cmd; atomic_t ref_cnt; -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) atomic_t net_ref_cnt; #endif @@ -367,7 +367,7 @@ extern void conn_info_show(struct seq_file *, struct iscsi_session *); /* nthread.c */ extern int iscsi_send(struct iscsi_conn *conn); -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) extern void iscsi_get_page_callback(struct page *page); extern void iscsi_put_page_callback(struct page *page); #endif diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 6326af2ec..71764fb2b 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -54,7 +54,7 @@ enum tx_state { TX_END, }; -#if defined(NET_PAGE_CALLBACKS_DEFINED) +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) static void iscsi_check_closewait(struct iscsi_conn *conn) { struct iscsi_cmnd *cmnd; @@ -367,7 +367,7 @@ static void close_conn(struct iscsi_conn *conn) conn->wr_state, session->exp_cmd_sn); #ifdef CONFIG_SCST_DEBUG { -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) struct iscsi_cmnd *rsp; #endif @@ -384,7 +384,7 @@ static void close_conn(struct iscsi_conn *conn) (cmnd->scst_cmd != NULL) ? cmnd->scst_cmd->state : -1, cmnd->data_waiting, atomic_read(&cmnd->ref_cnt), cmnd->pdu.bhs.sn, cmnd->parent_req, cmnd->pending); -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) TRACE_CONN_CLOSE_DBG("net_ref_cnt %d, sg %p", atomic_read(&cmnd->net_ref_cnt), cmnd->sg); if (cmnd->sg != NULL) { @@ -857,7 +857,7 @@ int istrd(void *arg) return 0; } -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) static inline void __iscsi_get_page_callback(struct iscsi_cmnd *cmd) { int v; @@ -1042,7 +1042,7 @@ static int write_data(struct iscsi_conn *conn) sock = conn->sock; -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) sock_sendpage = sock->ops->sendpage; #else if ((write_cmnd->parent_req->scst_cmd != NULL) && @@ -1057,7 +1057,7 @@ static int write_data(struct iscsi_conn *conn) while (1) { sendpage = sock_sendpage; -#ifdef NET_PAGE_CALLBACKS_DEFINED +#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) { static DEFINE_SPINLOCK(net_priv_lock); spin_lock(&net_priv_lock); diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.16.29.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.16.29.patch index 212901044..b66616eb8 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.16.29.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.16.29.patch @@ -33,7 +33,7 @@ diff -upr linux-2.6.16.29/include/linux/net.h linux-2.6.16.29/include/linux/net. #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.18.1.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.18.1.patch index 77ba5b911..7d6668dcf 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.18.1.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.18.1.patch @@ -33,7 +33,7 @@ diff -upr linux-2.6.18.1/include/linux/net.h linux-2.6.18.1/include/linux/net.h #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.21.1.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.21.1.patch index 1b326b752..725a9d093 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.21.1.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.21.1.patch @@ -33,7 +33,7 @@ diff -upr linux-2.6.21.1/include/linux/net.h linux-2.6.21.1/include/linux/net.h #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.22.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.22.patch index a424f525c..af3c26192 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.22.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.22.patch @@ -33,7 +33,7 @@ diff -upr linux-2.6.22/include/linux/net.h linux-2.6.22/include/linux/net.h #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.23.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.23.patch index f7c9a8bb7..f95178c0c 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.23.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.23.patch @@ -33,7 +33,7 @@ diff -upkr linux-2.6.23/include/linux/net.h linux-2.6.23/include/linux/net.h #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.24.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.24.patch index 012bec2e6..7c4e6323f 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.24.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.24.patch @@ -33,7 +33,7 @@ diff -upkr linux-2.6.24/include/linux/net.h linux-2.6.24/include/linux/net.h #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.25.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.25.patch index f25074420..bde18d8d1 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.25.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.25.patch @@ -35,7 +35,7 @@ diff -upkr linux-2.6.25/include/linux/net.h linux-2.6.25/include/linux/net.h #endif +/* Support for notification on zero-copy TCP transfer completion */ -+#define NET_PAGE_CALLBACKS_DEFINED ++#define CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION +typedef void (*net_get_page_callback_t)(struct page *page); +typedef void (*net_put_page_callback_t)(struct page *page); + diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.26.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.26.patch new file mode 100644 index 000000000..ff7250aaf --- /dev/null +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.26.patch @@ -0,0 +1,297 @@ +diff -upkr linux-2.6.26/include/linux/mm_types.h linux-2.6.26/include/linux/mm_types.h +--- linux-2.6.26/include/linux/mm_types.h 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/include/linux/mm_types.h 2008-07-22 20:30:21.000000000 +0400 +@@ -91,6 +91,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 ++ + #ifdef CONFIG_CGROUP_MEM_RES_CTLR + unsigned long page_cgroup; + #endif +diff -upkr linux-2.6.26/include/linux/net.h linux-2.6.26/include/linux/net.h +--- linux-2.6.26/include/linux/net.h 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/include/linux/net.h 2008-07-22 20:37:39.000000000 +0400 +@@ -60,6 +60,7 @@ typedef enum { + #ifdef __KERNEL__ + #include + #include ++#include + + #define SOCK_ASYNC_NOSPACE 0 + #define SOCK_ASYNC_WAITDATA 1 +@@ -342,5 +343,40 @@ extern int net_msg_cost; + extern int net_msg_burst; + #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); ++ ++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.26/net/core/skbuff.c linux-2.6.26/net/core/skbuff.c +--- linux-2.6.26/net/core/skbuff.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/core/skbuff.c 2008-07-22 20:28:41.000000000 +0400 +@@ -321,7 +321,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) +@@ -655,7 +655,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; + } +@@ -718,7 +718,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); +@@ -987,7 +987,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); +@@ -1156,7 +1156,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]; +@@ -1944,7 +1944,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; +@@ -2319,7 +2319,7 @@ struct sk_buff *skb_segment(struct sk_bu + BUG_ON(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.26/net/ipv4/ip_output.c linux-2.6.26/net/ipv4/ip_output.c +--- linux-2.6.26/net/ipv4/ip_output.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/ipv4/ip_output.c 2008-07-22 20:28:41.000000000 +0400 +@@ -1009,7 +1009,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]; + } +@@ -1167,7 +1167,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.26/net/ipv4/Makefile linux-2.6.26/net/ipv4/Makefile +--- linux-2.6.26/net/ipv4/Makefile 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/ipv4/Makefile 2008-07-22 20:35:05.000000000 +0400 +@@ -50,6 +50,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.26/net/ipv4/tcp.c linux-2.6.26/net/ipv4/tcp.c +--- linux-2.6.26/net/ipv4/tcp.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/ipv4/tcp.c 2008-07-22 20:28:41.000000000 +0400 +@@ -716,7 +716,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); + } + +@@ -921,7 +921,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; + } +@@ -962,9 +962,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.26/net/ipv4/tcp_output.c linux-2.6.26/net/ipv4/tcp_output.c +--- linux-2.6.26/net/ipv4/tcp_output.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/ipv4/tcp_output.c 2008-07-22 20:28:41.000000000 +0400 +@@ -805,7 +805,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.26/net/ipv4/tcp_zero_copy.c linux-2.6.26/net/ipv4/tcp_zero_copy.c +--- linux-2.6.26/net/ipv4/tcp_zero_copy.c 2008-07-22 20:12:35.000000000 +0400 ++++ linux-2.6.26/net/ipv4/tcp_zero_copy.c 2008-07-22 20:34:21.000000000 +0400 +@@ -0,0 +1,43 @@ ++/* ++ * 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; ++net_put_page_callback_t net_put_page_callback __read_mostly; ++ ++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); ++ ++EXPORT_SYMBOL(net_get_page_callback); ++EXPORT_SYMBOL(net_put_page_callback); +diff -upkr linux-2.6.26/net/ipv6/ip6_output.c linux-2.6.26/net/ipv6/ip6_output.c +--- linux-2.6.26/net/ipv6/ip6_output.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/ipv6/ip6_output.c 2008-07-22 20:28:41.000000000 +0400 +@@ -1336,7 +1336,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.26/net/Kconfig linux-2.6.26/net/Kconfig +--- linux-2.6.26/net/Kconfig 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/net/Kconfig 2008-07-22 20:50:41.000000000 +0400 +@@ -62,6 +62,17 @@ config INET + + Short answer: say Y. + ++config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION ++ bool "TCP/IP zero-copy transfer completion notification" ++ depends on INET ++ ---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/scst/ChangeLog b/scst/ChangeLog index b9ee18844..8f203cab6 100644 --- a/scst/ChangeLog +++ b/scst/ChangeLog @@ -1,6 +1,9 @@ Summary of changes between versions 1.0.0 and 1.0.1 --------------------------------------------------- + - Update for 2.6.26 + + - Minor fixes and cleanups Summary of changes between versions 0.9.5 and 1.0.0 diff --git a/scst/kernel/scst_exec_req_fifo-2.6.26.patch b/scst/kernel/scst_exec_req_fifo-2.6.26.patch new file mode 100644 index 000000000..f2c6734cf --- /dev/null +++ b/scst/kernel/scst_exec_req_fifo-2.6.26.patch @@ -0,0 +1,109 @@ +diff -upkr linux-2.6.26/drivers/scsi/scsi_lib.c linux-2.6.26/drivers/scsi/scsi_lib.c +--- linux-2.6.26/drivers/scsi/scsi_lib.c 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/drivers/scsi/scsi_lib.c 2008-07-22 20:24:44.000000000 +0400 +@@ -372,7 +372,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 +@@ -385,11 +385,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; +@@ -426,7 +429,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: +@@ -435,8 +438,53 @@ 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 -upkr linux-2.6.26/include/scsi/scsi_device.h linux-2.6.26/include/scsi/scsi_device.h +--- linux-2.6.26/include/scsi/scsi_device.h 2008-07-14 01:51:29.000000000 +0400 ++++ linux-2.6.26/include/scsi/scsi_device.h 2008-07-22 20:24:44.000000000 +0400 +@@ -333,6 +333,13 @@ 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_user.c b/scst/src/dev_handlers/scst_user.c index f1240c3f8..27d84a1a8 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -34,6 +34,24 @@ for details." #endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) +#define COMPLETION_INITIALIZER_ONSTACK(work) \ + ({ init_completion(&work); work; }) + +/* + * Lockdep needs to run a non-constant initializer for on-stack + * completions - so we use the _ONSTACK() variant for those that + * are on the kernel stack: + */ +#ifdef CONFIG_LOCKDEP +# define DECLARE_COMPLETION_ONSTACK(work) \ + struct completion work = COMPLETION_INITIALIZER_ONSTACK(work) +#else +# define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work) +#endif + +#endif + #define DEV_USER_MAJOR 237 #define DEV_USER_CMD_HASH_ORDER 6 @@ -318,7 +336,7 @@ static void cmd_insert_hash(struct scst_user_cmd *ucmd) list_add_tail(&ucmd->hash_list_entry, head); spin_unlock_irqrestore(&dev->cmd_lists.cmd_list_lock, flags); - TRACE_DBG("Inserted ucmd %p, h=%d", ucmd, ucmd->h); + TRACE_DBG("Inserted ucmd %p, h=%d (dev %s)", ucmd, ucmd->h, dev->name); return; } @@ -1466,6 +1484,8 @@ static int dev_user_reply_cmd(struct file *file, void __user *arg) if (res < 0) goto out_up; + TRACE_MGMT_DBG("Reply for dev %s", dev->name); + TRACE_BUFFER("Reply", &reply, sizeof(reply)); res = dev_user_process_reply(dev, &reply); @@ -1645,7 +1665,8 @@ static int dev_user_reply_get_cmd(struct file *file, void __user *arg) if (res < 0) goto out_up; - TRACE_DBG("ureply %Ld", (long long unsigned int)ureply); + TRACE_DBG("ureply %Ld (dev %s)", (long long unsigned int)ureply, + dev->name); cmd = kmem_cache_alloc(user_get_cmd_cachep, GFP_KERNEL); if (cmd == NULL) { @@ -1782,9 +1803,9 @@ static unsigned int dev_user_poll(struct file *file, poll_table *wait) spin_unlock_irq(&dev->cmd_lists.cmd_list_lock); - TRACE_DBG("Before poll_wait() (dev %p)", dev); + TRACE_DBG("Before poll_wait() (dev %s)", dev->name); poll_wait(file, &dev->cmd_lists.cmd_list_waitQ, wait); - TRACE_DBG("After poll_wait() (dev %p)", dev); + TRACE_DBG("After poll_wait() (dev %s)", dev->name); spin_lock_irq(&dev->cmd_lists.cmd_list_lock); @@ -2538,8 +2559,9 @@ static int __dev_user_set_opt(struct scst_user_dev *dev, TRACE_ENTRY(); - TRACE_DBG("parse_type %x, on_free_cmd_type %x, memory_reuse_type %x, " - "partial_transfers_type %x, partial_len %d", opt->parse_type, + TRACE_DBG("dev %s, parse_type %x, on_free_cmd_type %x, " + "memory_reuse_type %x, partial_transfers_type %x, " + "partial_len %d", dev->name, opt->parse_type, opt->on_free_cmd_type, opt->memory_reuse_type, opt->partial_transfers_type, opt->partial_len); @@ -2651,8 +2673,9 @@ static int dev_user_get_opt(struct file *file, void __user *arg) opt.swp = dev->swp; opt.has_own_order_mgmt = dev->has_own_order_mgmt; - TRACE_DBG("parse_type %x, on_free_cmd_type %x, memory_reuse_type %x, " - "partial_transfers_type %x, partial_len %d", opt.parse_type, + TRACE_DBG("dev %s, parse_type %x, on_free_cmd_type %x, " + "memory_reuse_type %x, partial_transfers_type %x, " + "partial_len %d", dev->name, opt.parse_type, opt.on_free_cmd_type, opt.memory_reuse_type, opt.partial_transfers_type, opt.partial_len); @@ -2888,13 +2911,17 @@ static int dev_user_cleanup_thread(void *arg) static int __init init_scst_user(void) { int res = 0; - struct class_device *class_member; struct max_get_reply { union { struct scst_user_get_cmd g; struct scst_user_reply_cmd r; }; }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) + struct class_device *class_member; +#else + struct device *dev; +#endif TRACE_ENTRY(); @@ -2942,12 +2969,21 @@ static int __init init_scst_user(void) goto out_class; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) class_member = class_device_create(dev_user_sysfs_class, NULL, - MKDEV(DEV_USER_MAJOR, 0), NULL, DEV_USER_NAME); + MKDEV(DEV_USER_MAJOR, 0), NULL, DEV_USER_NAME); if (IS_ERR(class_member)) { res = PTR_ERR(class_member); goto out_chrdev; } +#else + dev = device_create(dev_user_sysfs_class, NULL, MKDEV(DEV_USER_MAJOR, 0), + DEV_USER_NAME); + if (IS_ERR(dev)) { + res = PTR_ERR(dev); + goto out_chrdev; + } +#endif cleanup_thread = kthread_run(dev_user_cleanup_thread, NULL, "scst_usr_cleanupd"); @@ -2962,7 +2998,11 @@ out: return res; out_dev: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) class_device_destroy(dev_user_sysfs_class, MKDEV(DEV_USER_MAJOR, 0)); +#else + device_destroy(dev_user_sysfs_class, MKDEV(DEV_USER_MAJOR, 0)); +#endif out_chrdev: unregister_chrdev(DEV_USER_MAJOR, DEV_USER_NAME); @@ -2995,7 +3035,11 @@ static void __exit exit_scst_user(void) TRACE_MGMT_DBG("kthread_stop() failed: %d", rc); unregister_chrdev(DEV_USER_MAJOR, DEV_USER_NAME); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) class_device_destroy(dev_user_sysfs_class, MKDEV(DEV_USER_MAJOR, 0)); +#else + device_destroy(dev_user_sysfs_class, MKDEV(DEV_USER_MAJOR, 0)); +#endif class_destroy(dev_user_sysfs_class); scst_dev_handler_destroy_std_proc(&dev_user_devtype); diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index a3de3274a..d84079f73 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -1475,10 +1475,10 @@ void scst_put(void) } EXPORT_SYMBOL(scst_put); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) -static int scst_add(struct class_device *cdev) -#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static int scst_add(struct class_device *cdev, struct class_interface *intf) +#else +static int scst_add(struct device *cdev, struct class_interface *intf) #endif { struct scsi_device *scsidp; @@ -1486,34 +1486,49 @@ static int scst_add(struct class_device *cdev, struct class_interface *intf) TRACE_ENTRY(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) scsidp = to_scsi_device(cdev->dev); +#else + scsidp = to_scsi_device(cdev->parent); +#endif res = scst_register_device(scsidp); TRACE_EXIT(); return res; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) -static void scst_remove(struct class_device *cdev) -#else +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static void scst_remove(struct class_device *cdev, struct class_interface *intf) +#else +static void scst_remove(struct device *cdev, struct class_interface *intf) #endif { struct scsi_device *scsidp; TRACE_ENTRY(); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) scsidp = to_scsi_device(cdev->dev); +#else + scsidp = to_scsi_device(cdev->parent); +#endif scst_unregister_device(scsidp); TRACE_EXIT(); return; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) static struct class_interface scst_interface = { .add = scst_add, .remove = scst_remove, }; +#else +static struct class_interface scst_interface = { + .add_dev = scst_add, + .remove_dev = scst_remove, +}; +#endif static void __init scst_print_config(void) {