From 5c963d25e1c58650c294027c9a3e7bd62d27899d Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Sat, 21 Feb 2015 04:16:51 +0000 Subject: [PATCH] Merged revisions 5984,5988-5989 via svnmerge from svn+ssh://vlnb@svn.code.sf.net/p/scst/svn/trunk ........ r5984 | vlnb | 2015-01-21 21:03:17 -0800 (Wed, 21 Jan 2015) | 9 lines [PATCH] scst_local: Fix bidirectional command support scsi_setup_cmnd() sets sc_data_direction to DMA_TO_DEVICE for bidirectional commands. Hence test SCpnt->request->next_rq instead of sc_data_direction to figure out whether or not a command is bidirectional. Signed-off-by: Bart Van Assche ........ r5988 | vlnb | 2015-01-21 21:13:59 -0800 (Wed, 21 Jan 2015) | 27 lines scst_vdisk: Fix zero-copy read for tmpfs For some filesystems, e.g. tmpfs, address_space.readpage is NULL. Disable zero-copy reading for such filesystems. See also shmem_aops in mm/shmem.c. See also inode_init_always() and empty_aops in fs/inode.c. This patch avoids that the following call trace is triggered: BUG: unable to handle kernel NULL pointer dereference at (null) Call Trace: [] prepare_read+0x106/0x1d0 [scst_vdisk] [] fileio_alloc_data_buf+0xf0/0x330 [scst_vdisk] [] scst_prepare_space+0x9b/0x6e0 [scst] [] scst_process_active_cmd+0x545/0x840 [scst] [] scst_cmd_init_done+0x302/0x5d0 [scst] [] scst_cmd_init_stage1_done.constprop.37+0x12/0x20 [iscsi_scst] [] scsi_cmnd_start+0x25a/0x550 [iscsi_scst] [] cmnd_rx_start+0x148/0x1a0 [iscsi_scst] [] process_read_io+0x3b8/0x800 [iscsi_scst] [] scst_do_job_rd+0xc7/0x220 [iscsi_scst] [] istrd+0x16d/0x2e0 [iscsi_scst] [] kthread+0xed/0x110 [] ret_from_fork+0x7c/0xb0 Signed-off-by: Bart Van Assche ........ r5989 | vlnb | 2015-01-23 21:37:57 -0800 (Fri, 23 Jan 2015) | 5 lines scst_local: Rework data direction detection code Signed-off-by: Bart Van Assche ........ git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/3.0.x@6112 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/src/dev_handlers/scst_vdisk.c | 3 ++- scst_local/scst_local.c | 33 ++++++++++++------------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 32dfc8665..26f7f4cac 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -2686,7 +2686,8 @@ static int fileio_alloc_data_buf(struct scst_cmd *cmd) * copy. */ if (cmd->tgt_i_data_buf_alloced || - (cmd->data_direction & SCST_DATA_READ) == 0) { + (cmd->data_direction & SCST_DATA_READ) == 0 || + (virt_dev->fd && !virt_dev->fd->f_mapping->a_ops->readpage)) { p->use_zero_copy = false; } if (!p->use_zero_copy) diff --git a/scst_local/scst_local.c b/scst_local/scst_local.c index f39472add..4aec3d816 100644 --- a/scst_local/scst_local.c +++ b/scst_local/scst_local.c @@ -1068,22 +1068,8 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, sgl_count = scsi_sg_count(SCpnt); #endif - dir = SCST_DATA_NONE; - switch (SCpnt->sc_data_direction) { - case DMA_TO_DEVICE: - dir = SCST_DATA_WRITE; - scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt)); - scst_cmd_set_noio_mem_alloc(scst_cmd); - scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count); - break; - case DMA_FROM_DEVICE: - dir = SCST_DATA_READ; - scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt)); - scst_cmd_set_noio_mem_alloc(scst_cmd); - scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count); - break; - case DMA_BIDIRECTIONAL: -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24)) + if (scsi_bidi_cmnd(SCpnt)) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 24) /* Some of these symbols are only defined after 2.6.24 */ dir = SCST_DATA_BIDI; scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt)); @@ -1093,13 +1079,20 @@ static int scst_local_queuecommand_lck(struct scsi_cmnd *SCpnt, scst_cmd_set_tgt_sg(scst_cmd, scsi_in(SCpnt)->table.sgl, scsi_in(SCpnt)->table.nents); scst_cmd_set_tgt_out_sg(scst_cmd, sgl, sgl_count); - break; #endif - case DMA_NONE: - default: + } else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) { + dir = SCST_DATA_WRITE; + scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt)); + scst_cmd_set_noio_mem_alloc(scst_cmd); + scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count); + } else if (SCpnt->sc_data_direction == DMA_FROM_DEVICE) { + dir = SCST_DATA_READ; + scst_cmd_set_expected(scst_cmd, dir, scsi_bufflen(SCpnt)); + scst_cmd_set_noio_mem_alloc(scst_cmd); + scst_cmd_set_tgt_sg(scst_cmd, sgl, sgl_count); + } else { dir = SCST_DATA_NONE; scst_cmd_set_expected(scst_cmd, dir, 0); - break; } /* Save the correct thing below depending on version */