From 411fb4f623af5aadd6a496413d10012f44e2b23e Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Mon, 10 Jan 2011 18:34:29 +0000 Subject: [PATCH] - Update for 2.6.37 - Docs updated - Returning of DIRECT contexts by scst_estimate_context() disabled (see comment in the patch why) git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3203 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/ChangeLog | 2 + .../patches/put_page_callback-2.6.37.patch | 93 +++++++++---------- qla2x00t/qla2x00-target/ChangeLog | 2 + qla2x00t/qla_os.c | 22 +++-- scst/ChangeLog | 2 + scst/README | 15 +-- scst/README_in-tree | 15 +-- scst/include/scst.h | 34 +++++-- scst/kernel/scst_exec_req_fifo-2.6.37.patch | 39 ++++---- scst/src/scst_targ.c | 3 +- scst_local/README | 18 ++++ scst_local/scst_local.c | 38 +++++--- 12 files changed, 174 insertions(+), 109 deletions(-) diff --git a/iscsi-scst/ChangeLog b/iscsi-scst/ChangeLog index 4130231b5..bb6606276 100644 --- a/iscsi-scst/ChangeLog +++ b/iscsi-scst/ChangeLog @@ -1,6 +1,8 @@ Summary of changes between versions 2.0.0 and 2.1.0 --------------------------------------------------- + - Update to 2.6.37 + - Assigning CPU affinity to RD/WR threads added diff --git a/iscsi-scst/kernel/patches/put_page_callback-2.6.37.patch b/iscsi-scst/kernel/patches/put_page_callback-2.6.37.patch index bd2806e87..d2fefd01d 100644 --- a/iscsi-scst/kernel/patches/put_page_callback-2.6.37.patch +++ b/iscsi-scst/kernel/patches/put_page_callback-2.6.37.patch @@ -1,6 +1,6 @@ -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h ---- a/include/linux/mm_types.h -+++ b/include/linux/mm_types.h +diff -upkr linux-2.6.37/include/linux/mm_types.h linux-2.6.37/include/linux/mm_types.h +--- linux-2.6.37/include/linux/mm_types.h 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/include/linux/mm_types.h 2011-01-08 16:43:27.966430897 +0300 @@ -100,6 +100,18 @@ struct page { */ void *shadow; @@ -20,9 +20,9 @@ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h }; /* -diff --git a/include/linux/net.h b/include/linux/net.h ---- a/include/linux/net.h -+++ b/include/linux/net.h +diff -upkr linux-2.6.37/include/linux/net.h linux-2.6.37/include/linux/net.h +--- linux-2.6.37/include/linux/net.h 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/include/linux/net.h 2011-01-08 16:43:27.966430897 +0300 @@ -20,6 +20,7 @@ #include @@ -31,7 +31,7 @@ diff --git a/include/linux/net.h b/include/linux/net.h #define NPROTO AF_MAX -@@ -293,5 +294,44 @@ extern int kernel_sock_shutdown(struct socket *sock, +@@ -293,5 +294,44 @@ extern int kernel_sock_shutdown(struct s extern struct ratelimit_state net_ratelimit_state; #endif @@ -76,9 +76,9 @@ diff --git a/include/linux/net.h b/include/linux/net.h + #endif /* __KERNEL__ */ #endif /* _LINUX_NET_H */ -diff --git a/net/core/dev.c b/net/core/dev.c ---- a/net/core/dev.c -+++ b/net/core/dev.c +diff -upkr linux-2.6.37/net/core/dev.c linux-2.6.37/net/core/dev.c +--- linux-2.6.37/net/core/dev.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/core/dev.c 2011-01-08 16:43:27.970432318 +0300 @@ -3225,7 +3225,7 @@ pull: skb_shinfo(skb)->frags[0].size -= grow; @@ -88,10 +88,10 @@ diff --git a/net/core/dev.c b/net/core/dev.c memmove(skb_shinfo(skb)->frags, skb_shinfo(skb)->frags + 1, --skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); -diff --git a/net/core/skbuff.c b/net/core/skbuff.c ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -76,13 +76,13 @@ static struct kmem_cache *skbuff_fclone_cache __read_mostly; +diff -upkr linux-2.6.37/net/core/skbuff.c linux-2.6.37/net/core/skbuff.c +--- linux-2.6.37/net/core/skbuff.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/core/skbuff.c 2011-01-08 16:43:59.575095480 +0300 +@@ -76,13 +76,13 @@ static struct kmem_cache *skbuff_fclone_ static void sock_pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { @@ -107,7 +107,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c } static int sock_pipe_buf_steal(struct pipe_inode_info *pipe, -@@ -324,7 +324,7 @@ static void skb_release_data(struct sk_buff *skb) +@@ -324,7 +324,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++) @@ -116,7 +116,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c } if (skb_has_frag_list(skb)) -@@ -730,7 +730,7 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask) +@@ -730,7 +730,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]; @@ -125,7 +125,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c } skb_shinfo(n)->nr_frags = i; } -@@ -806,7 +806,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, +@@ -806,7 +806,7 @@ int pskb_expand_head(struct sk_buff *skb kfree(skb->head); } else { for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) @@ -179,7 +179,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c return p; } -@@ -1409,7 +1409,7 @@ static inline int spd_fill_page(struct splice_pipe_desc *spd, +@@ -1409,7 +1409,7 @@ static inline int spd_fill_page(struct s if (!page) return 1; } else @@ -188,7 +188,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c spd->pages[spd->nr_pages] = page; spd->partial[spd->nr_pages].len = *len; -@@ -2042,7 +2042,7 @@ static inline void skb_split_no_header(struct sk_buff *skb, +@@ -2042,7 +2042,7 @@ static inline void skb_split_no_header(s * where splitting is expensive. * 2. Split is accurately. We make this. */ @@ -197,7 +197,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c 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; -@@ -2164,7 +2164,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) +@@ -2164,7 +2164,7 @@ int skb_shift(struct sk_buff *tgt, struc to++; } else { @@ -206,7 +206,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c fragto->page = fragfrom->page; fragto->page_offset = fragfrom->page_offset; fragto->size = todo; -@@ -2186,7 +2186,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) +@@ -2186,7 +2186,7 @@ int skb_shift(struct sk_buff *tgt, struc fragto = &skb_shinfo(tgt)->frags[merge]; fragto->size += fragfrom->size; @@ -215,7 +215,7 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c } /* Reposition in the original skb */ -@@ -2587,7 +2587,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) +@@ -2587,7 +2587,7 @@ struct sk_buff *skb_segment(struct sk_bu while (pos < offset + len && i < nfrags) { *frag = skb_shinfo(skb)->frags[i]; @@ -224,9 +224,9 @@ diff --git a/net/core/skbuff.c b/net/core/skbuff.c size = frag->size; if (pos < offset) { -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c ---- a/net/ipv4/ip_output.c -+++ b/net/ipv4/ip_output.c +diff -upkr linux-2.6.37/net/ipv4/ip_output.c linux-2.6.37/net/ipv4/ip_output.c +--- linux-2.6.37/net/ipv4/ip_output.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/ipv4/ip_output.c 2011-01-08 16:43:27.974431382 +0300 @@ -1042,7 +1042,7 @@ alloc_new_skb: err = -EMSGSIZE; goto error; @@ -236,7 +236,7 @@ diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); frag = &skb_shinfo(skb)->frags[i]; } -@@ -1201,7 +1201,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, +@@ -1201,7 +1201,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) { @@ -245,9 +245,9 @@ diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c skb_fill_page_desc(skb, i, page, offset, len); } else { err = -EMSGSIZE; -diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile ---- a/net/ipv4/Makefile -+++ b/net/ipv4/Makefile +diff -upkr linux-2.6.37/net/ipv4/Makefile linux-2.6.37/net/ipv4/Makefile +--- linux-2.6.37/net/ipv4/Makefile 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/ipv4/Makefile 2011-01-08 16:43:27.974431382 +0300 @@ -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 @@ -256,9 +256,9 @@ diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ xfrm4_output.o -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c ---- a/net/ipv4/tcp.c -+++ b/net/ipv4/tcp.c +diff -upkr linux-2.6.37/net/ipv4/tcp.c linux-2.6.37/net/ipv4/tcp.c +--- linux-2.6.37/net/ipv4/tcp.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/ipv4/tcp.c 2011-01-08 16:43:27.974431382 +0300 @@ -806,7 +806,7 @@ new_segment: if (can_coalesce) { skb_shinfo(skb)->frags[i - 1].size += copy; @@ -289,10 +289,10 @@ diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c TCP_PAGE(sk) = page; } } -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c ---- a/net/ipv4/tcp_output.c -+++ b/net/ipv4/tcp_output.c -@@ -1080,7 +1080,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) +diff -upkr linux-2.6.37/net/ipv4/tcp_output.c linux-2.6.37/net/ipv4/tcp_output.c +--- linux-2.6.37/net/ipv4/tcp_output.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/ipv4/tcp_output.c 2011-01-08 16:43:27.974431382 +0300 +@@ -1082,7 +1082,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) { @@ -301,10 +301,9 @@ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c 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 ---- /dev/null -+++ b/net/ipv4/tcp_zero_copy.c +diff -upkr linux-2.6.37/net/ipv4/tcp_zero_copy.c linux-2.6.37/net/ipv4/tcp_zero_copy.c +--- linux-2.6.37/net/ipv4/tcp_zero_copy.c 2011-01-10 18:06:50.466106393 +0300 ++++ linux-2.6.37/net/ipv4/tcp_zero_copy.c 2011-01-08 16:43:27.978431250 +0300 @@ -0,0 +1,49 @@ +/* + * Support routines for TCP zero copy transmit @@ -355,10 +354,10 @@ new file mode 100644 + return res; +} +EXPORT_SYMBOL(net_set_get_put_page_callbacks); -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c ---- a/net/ipv6/ip6_output.c -+++ b/net/ipv6/ip6_output.c -@@ -1391,7 +1391,7 @@ alloc_new_skb: +diff -upkr linux-2.6.37/net/ipv6/ip6_output.c linux-2.6.37/net/ipv6/ip6_output.c +--- linux-2.6.37/net/ipv6/ip6_output.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/ipv6/ip6_output.c 2011-01-08 16:43:27.978431250 +0300 +@@ -1383,7 +1383,7 @@ alloc_new_skb: err = -EMSGSIZE; goto error; } @@ -367,9 +366,9 @@ diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); frag = &skb_shinfo(skb)->frags[i]; } -diff --git a/net/Kconfig b/net/Kconfig ---- a/net/Kconfig -+++ b/net/Kconfig +diff -upkr linux-2.6.37/net/Kconfig linux-2.6.37/net/Kconfig +--- linux-2.6.37/net/Kconfig 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/net/Kconfig 2011-01-08 16:43:27.978431250 +0300 @@ -72,6 +72,18 @@ config INET Short answer: say Y. diff --git a/qla2x00t/qla2x00-target/ChangeLog b/qla2x00t/qla2x00-target/ChangeLog index fee07f3fc..0df136e97 100644 --- a/qla2x00t/qla2x00-target/ChangeLog +++ b/qla2x00t/qla2x00-target/ChangeLog @@ -1,6 +1,8 @@ Summary of changes between versions 2.0.0 and 2.1.0 --------------------------------------------------- + - Update to 2.6.37 + - Complete NPIV support added. Particularly, now SCST core sees all the virtual targets and provide separate target-oriented access control for them. Thanks a lot to Uri Yanai and Dorit diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index b3ae52c17..df9f2f632 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -129,10 +129,14 @@ static int qla2xxx_slave_alloc(struct scsi_device *); static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time); static void qla2xxx_scan_start(struct Scsi_Host *); static void qla2xxx_slave_destroy(struct scsi_device *); -static int qla2x00_queuecommand(struct scsi_cmnd *cmd, +static int qla2x00_queuecommand_lck(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)); -static int qla24xx_queuecommand(struct scsi_cmnd *cmd, +static int qla24xx_queuecommand_lck(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +static DEF_SCSI_QCMD(qla2x00_queuecommand); +static DEF_SCSI_QCMD(qla24xx_queuecommand); +#endif static int qla2xxx_eh_abort(struct scsi_cmnd *); static int qla2xxx_eh_device_reset(struct scsi_cmnd *); static int qla2xxx_eh_target_reset(struct scsi_cmnd *); @@ -150,7 +154,11 @@ static int qla2x00_change_queue_type(struct scsi_device *, int); static struct scsi_host_template qla2x00_driver_template = { .module = THIS_MODULE, .name = QLA2XXX_DRIVER_NAME, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + .queuecommand = qla2x00_queuecommand_lck, +#else .queuecommand = qla2x00_queuecommand, +#endif .eh_abort_handler = qla2xxx_eh_abort, .eh_device_reset_handler = qla2xxx_eh_device_reset, @@ -186,7 +194,11 @@ static struct scsi_host_template qla2x00_driver_template = { struct scsi_host_template qla24xx_driver_template = { .module = THIS_MODULE, .name = QLA2XXX_DRIVER_NAME, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + .queuecommand = qla24xx_queuecommand_lck, +#else .queuecommand = qla24xx_queuecommand, +#endif .eh_abort_handler = qla2xxx_eh_abort, .eh_device_reset_handler = qla2xxx_eh_device_reset, @@ -415,7 +427,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport, } static int -qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +qla2x00_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; @@ -479,9 +491,8 @@ qc_fail_command: return 0; } - static int -qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) +qla24xx_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; @@ -546,7 +557,6 @@ qc24_fail_command: return 0; } - /* * qla2x00_eh_wait_on_command * Waits for the command to be returned by the Firmware for some diff --git a/scst/ChangeLog b/scst/ChangeLog index 26221ccf6..32140e698 100644 --- a/scst/ChangeLog +++ b/scst/ChangeLog @@ -1,6 +1,8 @@ Summary of changes between versions 2.0.0 and 2.1.0 --------------------------------------------------- + - Update to 2.6.37 + - Assigning CPU affinity to threads and connections added - Splitting of read/write CDBs for pass-through devices with sg_tablesize diff --git a/scst/README b/scst/README index d93351ccd..76edf9689 100644 --- a/scst/README +++ b/scst/README @@ -217,13 +217,13 @@ allows to work directly over a block device, e.g. local IDE or SCSI disk or ever disk partition, where there is no file systems overhead. Using block devices comparing to sending SCSI commands directly to SCSI mid-level via scsi_do_req()/scsi_execute_async() has advantage that data -are transferred via system cache, so it is possible to fully benefit from -caching and read ahead performed by Linux's VM subsystem. The only +are transferred via system cache, so it is possible to fully benefit +from caching and read ahead performed by Linux's VM subsystem. The only disadvantage here that in the FILEIO mode there is superfluous data copying between the cache and SCST's buffers. This issue is going to be -addressed in the next release. Virtual CDROM's are useful for remote -installation. See below for details how to setup and use VDISK device -handler. +addressed in one of the future releases. Virtual CDROM's are useful for +remote installation. See below for details how to setup and use VDISK +device handler. SCST user space device handler provides an interface between SCST and the user space, which allows to create pure user space devices. The @@ -1437,7 +1437,10 @@ sessions, which is enough. device. Note2: you need to restart SCST after you changed read-ahead settings - on the target. + on the target. It is a limitation of the Linux read ahead + implementation. It reads RA values for each file only when the file + is open and not updates them when the global RA parameters changed. + Hence, the need for vdisk to reopen all its files/devices. - You may need to increase amount of requests that OS on initiator sends to the target device. To do it on Linux initiators, run diff --git a/scst/README_in-tree b/scst/README_in-tree index 8f8c4d825..c177add76 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -118,13 +118,13 @@ allows to work directly over a block device, e.g. local IDE or SCSI disk or ever disk partition, where there is no file systems overhead. Using block devices comparing to sending SCSI commands directly to SCSI mid-level via scsi_do_req()/scsi_execute_async() has advantage that data -are transferred via system cache, so it is possible to fully benefit from -caching and read ahead performed by Linux's VM subsystem. The only +are transferred via system cache, so it is possible to fully benefit +from caching and read ahead performed by Linux's VM subsystem. The only disadvantage here that in the FILEIO mode there is superfluous data copying between the cache and SCST's buffers. This issue is going to be -addressed in the next release. Virtual CDROM's are useful for remote -installation. See below for details how to setup and use VDISK device -handler. +addressed in one of the future releases. Virtual CDROM's are useful for +remote installation. See below for details how to setup and use VDISK +device handler. "Performance" device handlers for disks, MO disks and tapes in their exec() method skip (pretend to execute) all READ and WRITE operations @@ -1257,7 +1257,10 @@ sessions, which is enough. device. Note2: you need to restart SCST after you changed read-ahead settings - on the target. + on the target. It is a limitation of the Linux read ahead + implementation. It reads RA values for each file only when the file + is open and not updates them when the global RA parameters changed. + Hence, the need for vdisk to reopen all its files/devices. - You may need to increase amount of requests that OS on initiator sends to the target device. To do it on Linux initiators, run diff --git a/scst/include/scst.h b/scst/include/scst.h index 7a4827c1d..120134cf7 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2819,17 +2819,21 @@ static inline void scst_sess_set_tgt_priv(struct scst_session *sess, /** * Returns TRUE if cmd is being executed in atomic context. * - * Note: checkpatch will complain on the use of in_atomic() below. You can - * safely ignore this warning since in_atomic() is used here only for debugging - * purposes. + * This function must be used outside of spinlocks and preempt/BH/IRQ + * disabled sections, because of the EXTRACHECK in it. */ static inline bool scst_cmd_atomic(struct scst_cmd *cmd) { int res = cmd->atomic; #ifdef CONFIG_SCST_EXTRACHECKS + /* + * Checkpatch will complain on the use of in_atomic() below. You + * can safely ignore this warning since in_atomic() is used here + * only for debugging purposes. + */ if (unlikely((in_atomic() || in_interrupt() || irqs_disabled()) && !res)) { - printk(KERN_ERR "ERROR: atomic context and non-atomic cmd\n"); + printk(KERN_ERR "ERROR: atomic context and non-atomic cmd!\n"); dump_stack(); cmd->atomic = 1; res = 1; @@ -2847,25 +2851,37 @@ static inline bool scst_cmd_prelim_completed(struct scst_cmd *cmd) return cmd->completed || test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags); } -static inline enum scst_exec_context __scst_estimate_context(bool direct) +static inline enum scst_exec_context __scst_estimate_context(bool atomic) { if (in_irq()) return SCST_CONTEXT_TASKLET; +/* + * We come here from many non reliable places, like the block layer, and don't + * have any reliable way to detect if we called under atomic context or not + * (in_atomic() isn't reliable), so let's be safe and disable this section + * for now to unconditionally return thread context. + */ +#if 0 else if (irqs_disabled()) return SCST_CONTEXT_THREAD; + else if (in_atomic()) + return SCST_CONTEXT_DIRECT_ATOMIC; else - return direct ? SCST_CONTEXT_DIRECT : + return atomic ? SCST_CONTEXT_DIRECT : SCST_CONTEXT_DIRECT_ATOMIC; +#else + return SCST_CONTEXT_THREAD; +#endif } static inline enum scst_exec_context scst_estimate_context(void) { - return __scst_estimate_context(0); + return __scst_estimate_context(false); } -static inline enum scst_exec_context scst_estimate_context_direct(void) +static inline enum scst_exec_context scst_estimate_context_atomic(void) { - return __scst_estimate_context(1); + return __scst_estimate_context(true); } /* Returns cmd's CDB */ diff --git a/scst/kernel/scst_exec_req_fifo-2.6.37.patch b/scst/kernel/scst_exec_req_fifo-2.6.37.patch index 35820d4d6..8f906f883 100644 --- a/scst/kernel/scst_exec_req_fifo-2.6.37.patch +++ b/scst/kernel/scst_exec_req_fifo-2.6.37.patch @@ -1,7 +1,6 @@ -diff --git a/block/blk-map.c b/block/blk-map.c -index 5d5dbe4..bc036bc 100644 ---- a/block/blk-map.c -+++ b/block/blk-map.c +diff -upkr linux-2.6.37/block/blk-map.c linux-2.6.37/block/blk-map.c +--- linux-2.6.37/block/blk-map.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/block/blk-map.c 2011-01-08 16:45:54.350430208 +0300 @@ -5,6 +5,8 @@ #include #include @@ -11,7 +10,7 @@ index 5d5dbe4..bc036bc 100644 #include /* for struct sg_iovec */ #include "blk.h" -@@ -273,6 +275,337 @@ int blk_rq_unmap_user(struct bio *bio) +@@ -274,6 +276,337 @@ int blk_rq_unmap_user(struct bio *bio) } EXPORT_SYMBOL(blk_rq_unmap_user); @@ -349,11 +348,10 @@ index 5d5dbe4..bc036bc 100644 /** * blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage * @q: request queue where request should be inserted -diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h -index aae86fd..c9a438e 100644 ---- a/include/linux/blkdev.h -+++ b/include/linux/blkdev.h -@@ -589,6 +589,8 @@ extern unsigned long blk_max_low_pfn, blk_max_pfn; +diff -upkr linux-2.6.37/include/linux/blkdev.h linux-2.6.37/include/linux/blkdev.h +--- linux-2.6.37/include/linux/blkdev.h 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/include/linux/blkdev.h 2011-01-08 16:45:54.350430208 +0300 +@@ -592,6 +592,8 @@ extern unsigned long blk_max_low_pfn, bl #define BLK_DEFAULT_SG_TIMEOUT (60 * HZ) #define BLK_MIN_SG_TIMEOUT (7 * HZ) @@ -362,7 +360,7 @@ index aae86fd..c9a438e 100644 #ifdef CONFIG_BOUNCE extern int init_emergency_isa_pool(void); extern void blk_queue_bounce(struct request_queue *q, struct bio **bio); -@@ -706,6 +708,9 @@ extern int blk_rq_map_kern(struct request_queue *, struct request *, void *, uns +@@ -709,6 +711,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 *, struct sg_iovec *, int, unsigned int, gfp_t); @@ -372,10 +370,9 @@ index aae86fd..c9a438e 100644 extern int blk_execute_rq(struct request_queue *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *, -diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h -index 9aaf5bf..0177996 100644 ---- a/include/linux/scatterlist.h -+++ b/include/linux/scatterlist.h +diff -upkr linux-2.6.37/include/linux/scatterlist.h linux-2.6.37/include/linux/scatterlist.h +--- linux-2.6.37/include/linux/scatterlist.h 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/include/linux/scatterlist.h 2011-01-08 16:45:54.354431761 +0300 @@ -3,6 +3,7 @@ #include @@ -384,7 +381,7 @@ index 9aaf5bf..0177996 100644 #include #include #include -@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, +@@ -218,6 +219,10 @@ size_t sg_copy_from_buffer(struct scatte size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen); @@ -395,11 +392,10 @@ index 9aaf5bf..0177996 100644 /* * Maximum number of entries that will be allocated in one piece, if * a list larger than this is required then chaining will be utilized. -diff --git a/lib/scatterlist.c b/lib/scatterlist.c -index 4ceb05d..caf58c4 100644 ---- a/lib/scatterlist.c -+++ b/lib/scatterlist.c -@@ -517,3 +517,132 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, +diff -upkr linux-2.6.37/lib/scatterlist.c linux-2.6.37/lib/scatterlist.c +--- linux-2.6.37/lib/scatterlist.c 2011-01-05 03:50:19.000000000 +0300 ++++ linux-2.6.37/lib/scatterlist.c 2011-01-08 16:45:54.401930472 +0300 +@@ -517,3 +517,132 @@ size_t sg_copy_to_buffer(struct scatterl return sg_copy_buffer(sgl, nents, buf, buflen, 1); } EXPORT_SYMBOL(sg_copy_to_buffer); @@ -532,3 +528,4 @@ index 4ceb05d..caf58c4 100644 + return res; +} +EXPORT_SYMBOL(sg_copy); + diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 0fdb96826..481e32333 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3974,8 +3974,7 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic) * for debugging purposes. */ EXTRACHECKS_BUG_ON(in_irq() || irqs_disabled()); - EXTRACHECKS_WARN_ON((in_atomic() || in_interrupt() || irqs_disabled()) && - !atomic); + EXTRACHECKS_WARN_ON((in_atomic() || in_interrupt()) && !atomic); cmd->atomic = atomic; diff --git a/scst_local/README b/scst_local/README index da24bab3f..b46b3929a 100644 --- a/scst_local/README +++ b/scst_local/README @@ -225,6 +225,24 @@ user space: For other connected initiators steps 3-6 should be repeated. +Compilation options +=================== + +There are the following compilation options, that could be commented +in/out in Makefile: + + - CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING - by default, when this option + is not defined, scst_local reschedules all commands for processing in + one of the SCST threads. If this option is defined, scst_local tries + to not do it, if possible (sometimes queuecommand() called under + various locks held), but instead process them in the submitter's + context. This is to increase performance, but as on 2.6.37 and below + Linux block layer doesn't work with such kind of reentrance, hence + this option disabled by default. Note! At the moment in + scst_estimate_context*() returning DIRECT contexts disabled, so this + option doesn't have any real effect. + + Change log ========== diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index 8ff757432..fabd0d93e 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -86,9 +86,6 @@ static unsigned long scst_local_trace_flag = SCST_LOCAL_DEFAULT_LOG_FLAGS; #define scsi_bufflen(cmd) ((cmd)->request_bufflen) #endif -#define TRUE 1 -#define FALSE 0 - #define SCST_LOCAL_VERSION "1.0.0" static const char *scst_local_version_date = "20100910"; @@ -795,7 +792,7 @@ static int scst_local_abort(struct scsi_cmnd *SCpnt) sess = to_scst_lcl_sess(scsi_get_device(SCpnt->device->host)); ret = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, SCpnt->tag, - FALSE, &dev_reset_completion); + false, &dev_reset_completion); /* Now wait for the completion ... */ wait_for_completion_interruptible(&dev_reset_completion); @@ -823,7 +820,7 @@ static int scst_local_device_reset(struct scsi_cmnd *SCpnt) lun = cpu_to_be16(SCpnt->device->lun); ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET, - (const uint8_t *)&lun, sizeof(lun), FALSE, + (const uint8_t *)&lun, sizeof(lun), false, &dev_reset_completion); /* Now wait for the completion ... */ @@ -853,7 +850,7 @@ static int scst_local_target_reset(struct scsi_cmnd *SCpnt) lun = cpu_to_be16(SCpnt->device->lun); ret = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_TARGET_RESET, - (const uint8_t *)&lun, sizeof(lun), FALSE, + (const uint8_t *)&lun, sizeof(lun), false, &dev_reset_completion); /* Now wait for the completion ... */ @@ -952,7 +949,7 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, if (!tgt_specific) { PRINT_ERROR("Unable to create tgt_specific (size %zu)", sizeof(*tgt_specific)); - return -ENOMEM; + return SCSI_MLQUEUE_HOST_BUSY; } tgt_specific->cmnd = SCpnt; tgt_specific->done = done; @@ -967,13 +964,17 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, /* * Tell the target that we have a command ... but first we need * to get the LUN into a format that SCST understand + * + * NOTE! We need to call it with atomic parameter true to not + * 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); + sizeof(lun), SCpnt->cmnd, SCpnt->cmd_len, true); if (!scst_cmd) { PRINT_ERROR("%s", "scst_rx_cmd() failed"); - return -ENOMEM; + return SCSI_MLQUEUE_HOST_BUSY; } scst_cmd_set_tag(scst_cmd, SCpnt->tag); @@ -1065,11 +1066,20 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, scst_cmd_set_tgt_priv(scst_cmd, SCpnt); #endif +/* + * Although starting from 2.6.37 queuecommand() called with no host_lock + * held, in reality without DEF_SCSI_QCMD() this doesn't work and leading + * to various problems like commands lost under highload. So, until that fixed + * we have to go ahead under host_lock, although absolutely don't need it. + * + * NOTE! At the moment in scst_estimate_context*() returning DIRECT contexts + * disabled, so this option doesn't have any real effect. + */ #ifdef CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING { struct Scsi_Host *h = SCpnt->device->host; spin_unlock_irq(h->host_lock); - scst_cmd_init_done(scst_cmd, scst_estimate_context_direct()); + scst_cmd_init_done(scst_cmd, scst_estimate_context_atomic()); spin_lock_irq(h->host_lock); } #else @@ -1085,6 +1095,10 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) +/* + * See comment in scst_local_queuecommand_lck() near + * CONFIG_SCST_LOCAL_FORCE_DIRECT_PROCESSING + */ static DEF_SCSI_QCMD(scst_local_queuecommand) #endif @@ -1554,7 +1568,7 @@ static void scst_local_release_adapter(struct device *dev) cancel_work_sync(&sess->aen_work); #endif - scst_unregister_session(sess->scst_sess, TRUE, NULL); + scst_unregister_session(sess->scst_sess, true, NULL); kfree(sess); @@ -1655,7 +1669,7 @@ unregister_dev: #endif unregister_session: - scst_unregister_session(sess->scst_sess, TRUE, NULL); + scst_unregister_session(sess->scst_sess, true, NULL); out_free: kfree(sess);